Shoot the Bullet

zoj3229:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=3442

题意:一个摄影师,在n天内给m个女神拍照。每个女神至少要拍Gi张照片,每一天只能给Ci个女神照相,每一天只能只能拍Di张照片,并且每个女神每天被拍的数量在[l,r]之间。问是否存在一种方案,满足条件,如果满足,最多可以照多少照片。

题解:这是一条有源汇的有上下界的最大流。首先源点s,t,源点和每一天i建立一边,上界为Di,下界为0,每个女神和t建立一边,上界是无穷,下界是Gi,因为上界是无穷大,所以下界等同为0,然后是每一天与对应的女神之间就是流量范围是[l,r],这里就可以转化成有上下界的流量处理,最后t-->s建立一边,容量是INF,这样就转化成无汇源的可行流。接下就是设超级源点ss,超级会点tt,把上面的图按照可行流的求解方式来求解。如果所有ss的出边都是满流,则有可行解。然后再跑一边最大流,此时源点时s,t,这里不再是超级源点ss,和会点tt。

  1 #include<iostream>
  2 #include<cstring>
  3 #include<cstdio>
  4 #include<algorithm>
  5 #include<queue>
  6 using namespace std;
  7 #define INF 1000000000
  8 const int N=1510;
  9 struct Node {
 10     int c;
 11     int f;
 12 }map[N][N];
 13 int sx,ex,n,m;
 14 int pre[N];
 15 int du[N],down[N][N];
 16 bool BFS(int x) { //BFS搜索层次网络
 17     memset(pre,0,sizeof(pre));
 18     queue< int > Q;
 19     Q.push(sx);
 20     pre[sx]=1;
 21     while(!Q.empty()) {
 22         int d=Q.front();
 23         Q.pop();
 24         for(int i=1; i<=x; i++) {
 25             if(!pre[i]&&map[d][i].c-map[d][i].f) {
 26                 pre[i]=pre[d]+1;
 27                 Q.push(i);
 28             }
 29         }
 30     }
 31     return pre[ex]!=0;
 32 }
 33 int dinic(int pos,int flow,int x) { //pos是顶点号,flow是当前顶点所能得到的流量,一次dinic只能求出一次增加的流量,
 34     int f=flow;
 35     if(pos==ex)
 36         return flow;
 37     for(int i=1; i<=x; i++) {
 38         if(map[pos][i].c-map[pos][i].f&&pre[pos]+1==pre[i]) {
 39             int a=map[pos][i].c-map[pos][i].f;
 40             int t=dinic(i,min(a,flow),x);
 41             map[pos][i].f+=t;
 42             map[i][pos].f-=t;
 43             flow-=t;
 44             if(flow<=0)break;
 45             //我最开始就是这里没弄明白,我不明白为什么要此顶点得到的流量减去改变量;
 46             //答案就在下面的  return f-flow;
 47         }
 48     }
 49     if(f-flow<=0)pre[pos]=-1;
 50     return f-flow;//其实这里返回给他前一层的就是这个t;因为t在层函数里面都有,所以所过避免重复就写成这样;
 51 }
 52 int solve(int x){
 53     int sum=0;
 54     while(BFS(x)) {
 55         sum+=dinic(sx,INF,x);
 56     }
 57     return sum;
 58 }
 59 int main() {
 60     int u,v,w,t1,t2,t3;
 61     while(~scanf("%d%d",&n,&m)) {
 62         int s=m+n+1,t=s+1;
 63         sx=t+1,ex=sx+1;
 64         memset(map,0,sizeof(map));
 65         memset(du,0,sizeof(du));
 66         memset(down,-1,sizeof(down));
 67         for(int i=1;i<=m; i++) {
 68             scanf("%d",&w);
 69             du[i]-=w;
 70             du[t]+=w;
 71             map[i][t].c+=INF;
 72         }
 73         for(int i=1;i<=n;i++){
 74           scanf("%d%d",&u,&v);
 75            map[s][i+m].c+=v;
 76            while(u--){
 77                scanf("%d%d%d",&t1,&t2,&t3);
 78                du[t1+1]+=t2;
 79                du[i+m]-=t2;
 80                down[i+m][t1+1]=t2;
 81                map[i+m][t1+1].c+=(t3-t2);
 82            }
 83         }
 84         map[t][s].c=INF;
 85         int sum=0;
 86        for(int i=1;i<=t;i++){
 87           if(du[i]>0){
 88                 map[sx][i].c+=du[i];
 89                 sum+=du[i];
 90           }
 91           else{
 92             map[i][ex].c+=(-du[i]);
 93           }
 94        }
 95        if(solve(n+m+4)!=sum)puts("-1");
 96        else{
 97           sx=s,ex=t;
 98           printf("%d\n",solve(n+m+2));
 99           for(int i=m+1;i<=n+m;i++){
100               for(int j=1;j<=m;j++){
101                  if(down[i][j]>=0){
102                     printf("%d\n",map[i][j].f+down[i][j]);
103                  }
104               }
105            }
106         }
107      puts("");
108     }
109     return 0;
110 }

时间: 2024-08-06 09:13:03

Shoot the Bullet的相关文章

ZOJ 3229 Shoot the Bullet

有源点汇点的上下界最大流问题... 建图很简单...按题意即可... 设原图 源点为 s 汇点 为 t,连一条t到s无下界上界无限大的边....设两个超级源S,T,像无源汇判断可行流的问题一样,记录每个点的in,连接到相应的超级源汇点...对S,T跑一遍最大流,并检测S所连边是否满流...如果不满足连可行流都没有无解...否则去掉S,T点(但总点数不要边...在这里错了一下午)对s,t跑一遍最大流.得到的结果既答案.....第一遍最大流保证了每个点的下界流得到满足,此时的图里还有很多自由流可以走

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

#pragma warning(disable:4996) #include <iostream> #include <cstring> #include <string> #include <vector> #include <cstdio> #include <algorithm> #include <cmath> #include <queue> #include <map> #include

ZOJ Problem Set - 3229 Shoot the Bullet 【有上下界网络流+流量输出】

题目:ZOJ Problem Set - 3229 Shoot the Bullet 分类:有源有汇有上下界网络流 题意:有 n 天和 m 个girls,然后每天给一部分girls拍照,每个girls 有拍照的下限,即最少要拍这么多张,然后每天有k个女孩拍照,摄影师最多可以拍num张,然后 k 个女该每天拍照数量值有上下限,然后问你有没有满足这样条件的给女孩拍照的最大方案,然后按照输入输出每天给女孩拍照的张数. 做这道题目推荐先做:这儿 分析:首先它让你判断能不能满足条件. 按照题目给出的条件很

ZOJ 3229 Shoot the Bullet 有源有汇带下界的最大流

链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3229 Shoot the Bullet Time Limit: 2 Seconds      Memory Limit: 32768 KB      Special Judge Gensokyo is a world which exists quietly beside ours, separated by a mystical border. It is a u

ZOJ 3229 Shoot the Bullet 无源汇上下界最大流

Shoot the Bullet Time Limit: 2 Seconds      Memory Limit: 32768 KB      Special Judge Gensokyo is a world which exists quietly beside ours, separated by a mystical border. It is a utopia where humans and other beings such as fairies, youkai(phantoms)

ZOJ 3229 Shoot the Bullet(有源汇有上下界的最大流)

ZOJ 3229 Shoot the Bullet 链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3229 题意:一个屌丝给m个女神拍照,计划拍照n天,每一天屌丝最多给C个女神拍照,每天拍照数不能超过D张,而且给每个女神 i 拍照有数量限制[Li,Ri],对于每个女神n天的拍照总和不能超过Gi,如果有解求屌丝最多能拍多少张照,并求每天给对应女神拍多少张照:否则输出-1. 思路: 有源汇有上下界的最大流 1. 在原先

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

Shoot the Bullethttp://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=3442 Time Limit: 2 Seconds      Memory Limit: 32768 KB      Special Judge Gensokyo is a world which exists quietly beside ours, separated by a mystical border. It is a utopia

【网络流】ZOJ 3229 Shoot the Bullet

题目链接: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3229 题目大意: n天给m个女孩拍照(1<=n<=365,1<=m<=1000),每个女孩X在n天里总共至少拍Gx张照片. 第k天可以给Ck个女孩拍照,当天总共最多拍Dk张照片,每个女孩这天被拍的数量在[Li,Ri]. 满足要求的条件下尽量多拍照. 求是否有可行解,没有输出-1,有的话输出最大流以及每天对该天能拍照的女孩的拍照数量(巨坑..怪我没

ZOJ3229 Shoot the Bullet

http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=20756 思路:就讲一下有源汇上下界最大流的做法吧!对于所有的边,就按照无源汇的做法做,然后建一条(t->s,inf)的边,然后先算ss到tt的最大流,看是否满足下界,然后不管这个流的答案,清空cnt和dis,然后算出s->t的最大流,就是答案. 1 #include<cstdio> 2 #include<cmath> 3 #include<i