poj Alice's Chance(最大流解题)
题目信息:Alice's Chance
解法:
利用最大网络流,以0表示源点,1表示汇点,以源点建立与每一天的边,边的容量是1,根据题目数据建立每周的给定的一天与每个电影之间的边,容量为1,建立每个film与汇点的边,容量为该部电影所需花费的时间,求出最大流和每部电影所花费天数的和比较,相等输出yes,否则输出No
源代码:
//Accepted 2196K 922MS //很险差点超时 #include<iostream> #include<queue> #include<cstring> using namespace std; #define VEX 500 int cpt[VEX][VEX],flow[VEX][VEX]; int sum; int f[7]; int Edmonds_Karp(int src,int sink,int node) { int d[VEX],pre[VEX];//d是增广路长度,pre记录前驱; int i,j; memset(flow,0,sizeof(flow)); while(true) { memset(pre,-1,sizeof(pre)); d[src]=0x7fffffff; queue<int> que; que.push(src); while(!que.empty() && pre[1]<0) { int t=que.front(); que.pop(); for(i=0;i<node;++i) { if(pre[i]<0 && (j=cpt[t][i]-flow[t][i])) { pre[i]=t; que.push(i); d[i]=min(d[t],j); } } } if(pre[sink]<0) break; for(i=1;i!=0;i=pre[i]) { flow[pre[i]][i]+=d[1]; flow[i][pre[i]]-=d[1]; } } for(j=i=0;i<node;j+=flow[0][i++]); return j; } int Init() { sum=0; int Maxw=0;//记录跨度最长的电影需要周数 int n,i,j; int D,W; int filmNum=0; memset(cpt,0,sizeof(cpt)); cin>>n; //0 is the source,1 is the sink,and the2--21 is the films,the 22--500 is the days for(i=22;i<500;++i) cpt[0][i]=1; while(n--) { for(i=0;i<7;++i) cin>>f[i]; cin>>D>>W; sum+=D; if(Maxw<W) Maxw=W; cpt[filmNum+2][1]=D; int temp=W*7; for(i=0;i<temp;i+=7) { for(j=0;j<7;++j) { cpt[22+i+j][filmNum+2]=f[j]; } } filmNum++; } return 22+7*Maxw; } int main() { int T;//the number of test cases cin>>T; while(T--) { int node=Init(); int temp=Edmonds_Karp(0,1,node); //cout<<temp<<" "<<sum<<endl; if(sum==temp) cout<<"Yes"<<endl; else cout<<"No"<<endl; } return 0; }