POJ 1698 Alice's Chance (网络流)

来源:互联网 发布:双色球246红球计算法 编辑:程序博客网 时间:2024/06/16 06:22

构图:

最多50周,350天

源点到每一天连一条容量为1的边,对于每个电影,可以拍摄的那些天连一条容量为1的边到这个电影,每个电影连一条容量为需求总天数的边到汇点。

看最大流是不是等于所有电影的需求总天数的和。

点数为天数+电影数+2。


代码:

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;#include <vector>#include <queue>#define maxn 500#define maxm 1000#define INF 10000000int N,M,s,t;struct Edge{int from,to,cap,flow;Edge(){}Edge(int s,int t,int c,int f):from(s),to(t),cap(c),flow(f){}};vector <Edge> edges;vector <int> G[maxn];bool vis[maxn];int d[maxn];int cur[maxn];struct film{int s[8];int D,W;}F[21];void init(){edges.clear();for(int i=0;i<=N;i++){G[i].clear();}}void addedge(int from,int to,int cap){edges.push_back(Edge(from,to,cap,0));edges.push_back(Edge(to,from,0,0));M=edges.size();G[from].push_back(M-2);G[to].push_back(M-1);}bool bfs(){memset(vis,0,sizeof(vis));queue<int> Q;Q.push(s);d[s]=0;vis[s]=1;while(!Q.empty()){int x=Q.front();Q.pop();for(int i=0;i<G[x].size();i++){Edge &e=edges[G[x][i]];if(!vis[e.to]&&e.cap>e.flow){vis[e.to]=1;d[e.to]=d[x]+1;Q.push(e.to);}}}return vis[t];}int dfs(int x,int a){if(x==t||a==0) return a;int flow=0,f;for(int &i=cur[x];i<G[x].size();i++){Edge &e=edges[G[x][i]];if(d[x]+1==d[e.to]&&(f=dfs(e.to,min(a,e.cap-e.flow)))>0){e.flow+=f;edges[G[x][i]^1].flow-=f;flow+=f;a-=f;if(a==0) break;}}return flow;}int Maxflow(){int flow=0;while(bfs()){memset(cur,0,sizeof(cur));flow+=dfs(s,INF);}return flow;}int main(){int T;scanf("%d",&T);while(T--){int nm;scanf("%d",&nm);int Maxw=0;for(int i=0;i<nm;i++){for(int j=1;j<=7;j++){scanf("%d",&F[i].s[j]);}scanf("%d%d",&F[i].D,&F[i].W);Maxw=max(Maxw,F[i].W);}N=Maxw*7+nm+1;init();for(int i=1;i<=Maxw*7;i++){addedge(0,i,1);}int tot=0;for(int i=0;i<nm;i++){int cur=Maxw*7+i+1;for(int j=1;j<=7;j++){if(F[i].s[j]){for(int k=0;k<F[i].W;k++){addedge(k*7+j,cur,1);}}}addedge(cur,N,F[i].D);tot+=F[i].D;}s=0;t=N;if(tot==Maxflow()){printf("Yes\n");}else printf("No\n");}return 0;}

0 0