题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=3442

题目大意:

一个屌丝给m个女神拍照,计划拍照n天,每一天屌丝给给定的C个女神拍照,每天拍照数不能超过D张,而且给每个女神i拍照有数量限制[Li,Ri],对于每个女神n天的拍照总和不能少于Gi,如果有解求屌丝最多能拍多少张照,并求每天给对应女神拍多少张照;否则输出-1。

解题思路:

有源汇带上下界的最大流,我也是第一次写。

说下建图:

①源点S到第i天流量为D[i]的边(上界为D[i],下界为0)

②第i天向女孩连流量为r-l的边(上界为r,下界为l)

③女孩向汇点T连流量为G[i]的边(上界为INF,下界为G[i])

④汇点向源点连流量为INF的边,使其变成无源汇图。(上界为INF,下界为0)

⑤out[i]为i点的出边下界和,in[i]为i点的入边下界和,若in[i]-out[i]>0,则从附加源点SS向i连流量为in[i]-out[i]的边,

若in[i]-out[i]<0,则从i点向附加汇点TT连流量为out[i]-in[i]的边。

具体求法,就是先求出改图是否存在可行流,即求有源汇上下界可行流,通过从T->连流量为INF的边即可将图变为无源汇图,这样就可以转换为无源汇上下界可行流求解。

若存在可行流,则再求一次S->T的最大流即为答案。

(这句话从网上找的)

为什么呢?因为第一次SS->TT只是求得所有满足下界的流量,而残留网络(S,T)路上还有许多自由流(没有和超级源点和超级汇点连接的边)没有流满,所有最终得到的ans=(第一次流满下界的流+第二次能流通的自由流)。

说起来ZOJ真是害我不浅啊,今天刚开始写上下界的题目,ZOJ 2314 low数组开小了一直TLE。。。。 然后这题忘记输出空行一直WA。。。 然后我每次都以为是自己写的问题debug好几个小时,难受啊。

代码

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
#define LL long long
#define pii pair<int,int>
#define pll pair<long long,long long>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
#define FAST_IO ios::sync_with_stdio(false);cin.tie(0);
#define bug cout<<"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"<<endl;
#define bugc(_) cout << (#_) << " = " << (_) << endl;
using namespace std;
const int N=2e3+;
const int M=1e5+;
const int INF=0x3f3f3f3f; struct node{
int to,next,flow;
}edge[M*]; int cnt,st,en;
int head[N],dep[N],out[N],in[N],low[M],G[N],D[N]; void init(){
cnt=;
memset(head,,sizeof(head));
memset(out,,sizeof(out));
memset(in,,sizeof(in));
} void link(int u,int v,int flow){
edge[cnt]=node{v,head[u],flow};
head[u]=cnt++;
edge[cnt]=node{u,head[v],};
head[v]=cnt++;
} int bfs(){
memset(dep,,sizeof(dep));
dep[st]=;
queue<int>q;
q.push(st);
while(!q.empty()){
int u=q.front();
q.pop();
for(int i=head[u];i;i=edge[i].next){
node t=edge[i];
if(t.flow&&!dep[t.to]){
dep[t.to]=dep[u]+;
q.push(t.to);
}
}
}
return dep[en];
} int dfs(int u,int fl){
if(en==u) return fl;
int tmp=;
for(int i=head[u];i&&fl;i=edge[i].next){
node &t=edge[i];
if(t.flow&&dep[t.to]==dep[u]+){
int x=dfs(t.to,min(t.flow,fl));
if(x>){
tmp+=x;
fl-=x;
t.flow-=x;
edge[i^].flow+=x;
}
}
}
if(!tmp) dep[u]=-;
return tmp;
} int dinic(int S,int T){
st=S,en=T;
int ans=;
while(bfs()){
while(int d=dfs(st,INF))
ans+=d;
}
return ans;
} int main(){
int n,m;
while(~scanf("%d%d",&n,&m)){
init();
int S=,T=n+m+,SS=n+m+,TT=n+m+;
for(int i=;i<=m;i++) scanf("%d",&G[i]);
int num=,sum=;
for(int i=;i<=n;i++){
int C;
scanf("%d%d",&C,&D[i]);
for(int j=;j<=C;j++){
int id,l,r;
scanf("%d%d%d",&id,&l,&r);
id++;
link(i,id+n,r-l);
low[++num]=l;
out[i]+=l;
in[id+n]+=l;
}
}
link(T,S,INF);
for(int i=;i<=n;i++){
link(S,i,D[i]); //D[i]是上限,下限为0,因为每天最多拍D[i]张照片
}
for(int i=;i<=m;i++){
link(i+n,T,INF);//G[i]是下限,因为每个人至少要G[i]张照片
in[T]+=G[i];
out[i+n]+=G[i];
}
for(int i=;i<=n+m+;i++){
int tmp=in[i]-out[i];
if(tmp>) link(SS,i,tmp),sum+=tmp;
else if(tmp<) link(i,TT,-tmp);
}
int ans=dinic(SS,TT);
if(ans==sum){
ans=dinic(S,T);
printf("%d\n",ans);
for(int i=;i<=num;i++){
printf("%d\n",edge[i*+].flow+low[i]);
}
}
else
puts("-1");
puts("");
}
return ;
}

ZOJ 3229 Shoot the Bullet(有源汇上下界最大流)的更多相关文章

  1. ZOJ - 3229 Shoot the Bullet (有源汇点上下界最大流)

    题意:要在n天里给m个女生拍照,每个女生有拍照数量的下限Gi,每天有拍照数量的上限Di,每天当中每个人有拍照的上限Lij和Rij.求在满足限制的基础上,所有人最大能拍多少张照片. 分析:抛开限制,显然 ...

  2. zoj 3229 Shoot the Bullet(无源汇上下界最大流)

    题目:Shoot the Bullet 收藏:http://www.tuicool.com/articles/QRr2Qb 把每一天看成一个点,每个女孩也看成一个点,增加源和汇s.t,源向每一天连上[ ...

  3. ZOJ 3229 Shoot the Bullet | 有源汇可行流

    题目: 射命丸文要给幻想乡的居民照相,共照n天m个人,每天射命丸文照相数不多于d个,且一个人n天一共被拍的照片不能少于g个,且每天可照的人有限制,且这些人今天照的相片必须在[l,r]以内,求是否有可行 ...

  4. 【有源汇上下界最大流】ZOJ 3229 Shoot the Bullet

    题目链接: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3229 题目大意: n天给m个女孩拍照(1<=n<= ...

  5. zoj 3229 Shoot the Bullet(有源汇上下界最大流)

    Shoot the Bullethttp://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=3442 Time Limit: 2 Second ...

  6. Shoot the Bullet(ZOJ3229)(有源汇上下界最大流)

    描述 ensokyo is a world which exists quietly beside ours, separated by a mystical border. It is a utop ...

  7. 【有源汇上下界费用流】BZOJ 3876 [Ahoi2014]支线剧情

    题目链接: http://www.lydsy.com:808/JudgeOnline/problem.php?id=3876 题目大意: 给定一张拓扑图(有向无环图),每条边有边权,每次只能从第一个点 ...

  8. POJ2396 Budget [有源汇上下界可行流]

    POJ2396 Budget 题意:n*m的非负整数矩阵,给出每行每列的和,以及一些约束关系x,y,>=<,val,表示格子(x,y)的值与val的关系,0代表整行/列都有这个关系,求判断 ...

  9. 有源汇上下界可行流(POJ2396)

    题意:给出一个n*m的矩阵的每行和及每列和,还有一些格子的限制,求一组合法方案. 源点向行,汇点向列,连一条上下界均为和的边. 对于某格的限制,从它所在行向所在列连其上下界的边. 求有源汇上下界可行流 ...

随机推荐

  1. 91 Testing Linux学习笔记

    91 Testing Linux学习笔记... 学习地址:91Testing 的Linux教程=====================学习网址:http://www.91testing.net/ar ...

  2. TestCase / test plan / test case

    s 测试计划 分析测试需求 制定测试策略 制定测试计划 评审测试计划 测试准备 编写测试案例 评审测试案例 准备测试环境 准备测试数据 准备配置项 测试执行 检查测试准入(环境.数据.配置.案例等) ...

  3. Swift学习笔记6

    1.用类型检查操作符(is)来检查一个实例是否属于特定子类型.若实例属于那个子类型,类型检查操作符返回 true,否则返回 false. 2.某类型的一个常量或变量可能在幕后实际上属于一个子类.当确定 ...

  4. Spark简介安装和简单例子

    Spark简介安装和简单例子 Spark简介 Spark是一种快速.通用.可扩展的大数据分析引擎,目前,Spark生态系统已经发展成为一个包含多个子项目的集合,其中包含SparkSQL.Spark S ...

  5. Java编程思想 学习笔记3

    三.操作符 1.优先级 当一个表达式中存在多个操作符时,操作符的优先级就决定了各部分的计算顺序.程序员常常忘记其他优先级规则,所以应该用括号明确规定计算顺序. 当编译器观察到一个String后面紧跟着 ...

  6. Python基础(正则、序列化、常用模块和面向对象)-day06

    写在前面 上课第六天,打卡: 天地不仁,以万物为刍狗: 一.正则 - 正则就是用一些具有特殊含义的符号组合到一起(称为正则表达式)来描述字符或者字符串的方法: - 在线正则工具:http://tool ...

  7. IDEA不生成WAR包,报错

    com.intellij.javaee.oss.admin.jmx.JmxAdminException: com.intellij.execution.ExecutionExceptionProjec ...

  8. SmartUpload文件上传组件的使用教程

    在项目中使用SmartUpload组件可以进行文件的上传和下载操作 使用步骤 1.导入jar包,进行build path操作 2.编写文件上传页面,代码如下 <form action=" ...

  9. android contentprovider内容提供者

    contentprovider内容提供者:让其他app可以访问私有数据库(文件) 1.AndroidManifest.xml 配置provider <?xml version="1.0 ...

  10. 第5月第6天 NSOperation isConcurrent category同名覆盖

    1. @implementation AFURLConnectionOperation ... - (BOOL)isConcurrent { return YES; } NSOperation调用st ...