【有源汇上下界最大流】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,有的话输出最大流以及每天对该天能拍照的女孩的拍照数量(巨坑。。怪我没读清题意。wa了好久)。

  数据输入:

    最多40组数据,多组数据,第一行两个数n和m,第二行m个数Gx。

    接下来输入n天的信息,第一行为每天的Ck,Dk,接下来C行输入今天可以拍的女孩编号T(从0开始),L,R。

题目思路:

  【有源汇上下界最大流】

  设源s和汇t,s向第i天连(0,Di)的边,第i天向当天的Ck个女孩连(Li,Ri)的边,最后每个女孩向t连(Gi,∞)的边。

  这样这题就转化成有上下界的最大流了。

  接下来设超级源S和超级汇T,将有上下界的图转成无上下界的图。

  从S到T跑一边最大流,如果每条S的出边都满流则有解,否则无解。

  有解的情况下把S和T删掉(听说不删也可以?),从s到t跑一边最大流,即为答案(别忘了加上下界)。

  

  建图方法:

  设每条边上界为c,下界为b,将每条边的上界改为c-b。

  我们开设一个数组in[]来记录每个节点的流量情况。

  in[i]=Σi入下界i出下界(i节点所有入流下界之和-i节点所有出流下界之和)。

  当in[i]大于0的时候,S到i连一条流量为in[i]的边。

  当in[i]小于0的时候,i到T连一条流量为-in[i]的边。

  最后对(S,T)求一次最大流即可,当所有附加边全部满流时(S的出边都满流时),有可行解。

  

  

  1 //
  2 //by coolxxx
  3 //
  4 #include<iostream>
  5 #include<algorithm>
  6 #include<string>
  7 #include<iomanip>
  8 #include<memory.h>
  9 #include<time.h>
 10 #include<stdio.h>
 11 #include<stdlib.h>
 12 #include<string.h>
 13 #include<stdbool.h>
 14 #include<math.h>
 15 #define min(a,b) ((a)<(b)?(a):(b))
 16 #define max(a,b) ((a)>(b)?(a):(b))
 17 #define abs(a) ((a)>0?(a):(-(a)))
 18 #define lowbit(a) (a&(-a))
 19 #define sqr(a) (a)*(a)
 20 #define swap(a,b) (a)^=(b),(b)^=(a),(a)^=(b)
 21 #define eps 1e-8
 22 #define MAX 0x7f7f7f7f
 23 #define INF 20000
 24 #define PI 3.1415926535897
 25 #define N 2004
 26 #define M 2000004
 27 using namespace std;
 28 int n,m,cas,lll,ans;
 29 int S,T,nn,s,t;
 30 int last[N],in[N],d[N],vd[N],day[400];
 31 int low[M];
 32 struct xxx
 33 {
 34     int next,to,f;
 35 }e[M];
 36 void add(int x,int y,int f)
 37 {
 38     e[++lll].next=last[x];
 39     last[x]=lll;
 40     e[lll].to=y;
 41     e[lll].f=f;
 42 }
 43 void link(int x,int y,int f)
 44 {
 45     add(x,y,f);
 46     add(y,x,0);
 47 }
 48 void build()
 49 {
 50     int i,j,f,x,y,b,c;
 51     lll=1;ans=0;
 52     scanf("%d",&m);
 53     s=n+m+1;t=n+m+2;
 54     for(i=1;i<=m;i++)
 55     {
 56         scanf("%d",&x);//Gx
 57         //link(n+i,t,MAX-x);
 58         in[n+i]-=x;in[t]+=x;
 59     }
 60     for(i=1;i<=n;i++)
 61     {
 62         scanf("%d%d",&x,&day[i]);//C D
 63         //link(s,i,f);
 64         for(j=1;j<=x;j++)
 65         {
 66             scanf("%d%d%d",&y,&b,&c);
 67             y++;
 68             link(i,n+y,c-b);
 69             in[i]-=b;in[n+y]+=b;
 70             low[++low[0]]=b;
 71         }
 72     }
 73     S=t+1;
 74     T=t+2;
 75     nn=n+m+4;
 76     for(i=1;i<=n+m+2;i++)
 77     {
 78         if(in[i]>0)link(S,i,in[i]);
 79         if(in[i]<0)link(i,T,-in[i]);
 80     }
 81     for(i=1;i<=m;i++)link(n+i,t,MAX);
 82     for(i=1;i<=n;i++)link(s,i,day[i]);
 83     link(t,s,MAX);
 84 }
 85 int sap(int u,int f,int T)
 86 {
 87     int i,tt,asp=0,mix=nn-1;
 88     if(u==T)return f;
 89     for(i=last[u];i;i=e[i].next)
 90     {
 91         if(e[i].f>0)
 92         {
 93             if(d[u]==d[e[i].to]+1)
 94             {
 95                 tt=sap(e[i].to,min(f-asp,e[i].f),T);
 96                 asp+=tt;
 97                 e[i].f-=tt;
 98                 e[i^1].f+=tt;
 99                 if(asp==f || d[S]==nn)
100                     return asp;
101             }
102             mix=min(mix,d[e[i].to]);
103         }
104     }
105     if(asp!=0)return asp;
106     if(!--vd[d[u]])d[S]=nn;
107     else vd[d[u]=mix+1]++;
108     return asp;
109 }
110 void maxflow(int S,int T)
111 {
112     int f;
113     memset(d,0,sizeof(d));
114     memset(vd,0,sizeof(vd));
115     vd[0]=nn;
116     while(d[S]<nn)
117     {
118         f=sap(S,MAX,T);
119         ans+=f;
120     }
121 }
122 int main()
123 {
124     #ifndef ONLINE_JUDGE
125 //    freopen("1.txt","r",stdin);
126 //    freopen("2.txt","w",stdout);
127     #endif
128     int i,j,f;
129 //    while(~scanf("%s",s))
130     while(~scanf("%d",&n) && n)
131     {
132         build();
133         maxflow(S,T);
134         for(i=last[S],f=1;i;i=e[i].next)
135         {
136             if(e[i].f>0)
137             {
138                 f=0;
139                 break;
140             }
141         }
142         if(!f)
143             puts("-1");
144         else
145         {
146             last[S]=last[T]=0;
147             ans=0;
148             maxflow(s,t);
149             printf("%d\n",ans);
150             for(i=1;i<=low[0];i++)
151                 printf("%d\n",low[i]+e[(i<<1)^1].f);
152         }
153         low[0]=0;
154         memset(in,0,sizeof(in));
155         memset(last,0,sizeof(last));
156         puts("");
157     }
158     return 0;
159 }
160 
161 
162 /*
163 //
164 
165 //
166 */
View Code

 

posted @ 2016-03-27 01:34  Cool639zhu  阅读(217)  评论(0编辑  收藏  举报