题目链接: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. Struts2中遇到的问题

    问题1: 最近在学习的时候用到了Struts2.5,在一系列操作之后Tomcat部署成功了,然而之后在测试的时候却出现了问题,网页无法正常响应,并且报出了Wrong method was define ...

  2. jQuery基础 (一)——样式篇(认识jQuery)

    一.认识 //等待dom元素加载完毕. $(document).ready(function(){ alert("Hello World!"); }); 二.jQuery对象与DO ...

  3. java gc

    mark下来 https://plumbr.eu/handbook/what-is-garbage-collection

  4. TIdHTTP get参数带中文解决方法--请求报文

    Post 看起来稍微复杂先,暂不讨论.post 目前按照一般方法有中文名也可以. 拼接时:pointname=九记餐厅&begintime=2017-03-01 00:00:00& 有 ...

  5. python - 练习(获取windows硬件信息)

    import subprocess import re # info = subprocess.Popen("systeminfo",shell=True,stdout=subpr ...

  6. Keil MDK忽略警告:文件末尾空白行警告

    使用Keil MDK调试程序的时候,没有习惯在每个文件的末尾增加一个空白行,结果文件一多,编译时产生的警告就一大堆,排错都得用滚轮滚好久,就一个空白行还得出警告,烦死了,烦死了,烦死了!实在受不了了, ...

  7. Java的IO流——(七)

    目录结构:

  8. Dubbo多版本

    当服务提供者提供的服务接口出现不兼容升级时,可以设置版本号,使用多个版本号(version)进行过渡. 1).服务提供者配置文件 <dubbo:service ref="userSer ...

  9. ubuntu16.04安装opencv2.4.13

    1.更新 sudo apt-get update sudo apt-get upgrade 2.安装关联库 2.1 搭建C/C++编译环境 sudo apt-get install build-ess ...

  10. UML和模式应用5:细化阶段(9)---迈向对象设计

    1.前言 开发者如何设计对象,可以采用如下三种方式: 编码:在编码的同时进行设计 绘图然后编码:绘制一些UML,然后转到如上编码方式,在集成开发环境中编码 只绘图,不编码:使用工具从图中生成一切 本章 ...