题目链接: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. js位操作

    1.&(与) 都是1才是1 例如:14&15  (14  二进制  1110 15  二进制   1111 &与的结果  1110  ---->结果14) (14& ...

  2. jenkins ansible 附zabbix_agent批量安装示例

    插件:Ansible plugin 一.ansible ad-hoc command 二.ansible-playbook 批量部署zabbix-agent示例: playbook 目录及文件组成 [ ...

  3. Oracle导出数据中的prompt,set feedback 等是什么意思

    prompt 显示后面的提示,相当于一般的操作系统命令echo,输出后面的信息Importing table t_testset feedback off 1.set feedback 有三种方式: ...

  4. Easyui和IE浏览器的兼容问题

    现在Easyui版本已经更新到1.3.4,今天下载最新的版本,同时下载了IETestert软件,分别模拟IE浏览器5.5,6.0,7.0,8.0和9.0的环境进行测试. Easyui1.3.3与1.3 ...

  5. ruby导出exl方式

    class Demo print "hello world" require "spreadsheet" #设置表格的编码为utf-8 Spreadsheet. ...

  6. Math.random()和UUID.randomUUID().toString()性能对比【纯原】

    Math.random()和UUID.randomUUID().toString()性能对比 不言而喻,因为Math.random()不需要保证唯一性,所做的操作远比UUID消耗更小的性能, 在部分要 ...

  7. Executor, ExecutorService 和 Executors 间的不同

    java.util.concurrent.Executor, java.util.concurrent.ExecutorService, java.util.concurrent. Executors ...

  8. PHP7 学习笔记(五)安装event扩展(libevent)

    一.描述:有效安排I/O,时间和信号的扩展 使用可用于特定平台的最佳I/O通知机制的事件,是PHP基础设施的libevent端口. 二.下载地址:http://pecl.php.net/package ...

  9. JAVA Socket 编程---Socket 和 ServerSocket

    一,Socket Socket的选项 1) TCP_NODELAY:默认值为false.表示采用Negale算法.当设置为true时,表示关闭Socket缓冲,立即发送数据. Socket默认发送数据 ...

  10. 二、主目录 Makefile 分析(3)

    2.8 编译选项 重新回到 主 makefile 中执行 2.8.1 u-boot  的编译顺序 代码166 到 189 行,这些是 u-boot 文件编译的顺序,由代码可以看到,首先是从cpu/$( ...