poj 1698 Alice's Chance 网络流

来源:互联网 发布:淘宝无线流量来源 编辑:程序博客网 时间:2024/05/23 05:08

题目大意:Alice要拍电影,给出每一部电影可以在哪一天进行拍摄(星期一到星期日,1表示可以,0表示不可以)、这部电影需要拍摄的总天数和在第几个星期前需要拍摄完成,Alice每天只能拍一部电影。

如果全部可以完成输出Yes,否则输出No


这道题难点主要是构图,网络流部分直接套模板就行

建立超级源点和超级汇点;

将源点与每一部电影连一条容量为需要拍摄天数(d)的边;

某一天如果可以进行拍摄将每部电影和那天连一条容量为1的边(反正最多只有350天);

将每一天都向汇点连一条容量为1的边。

构图详细的看代码就好了,很容易理解


跑最大流,用答案和拍电影需要的总天数比较

我用的是dinic

#include<cstdio>#include<vector>#include<queue>#include<cstring>using namespace std;const int MAXN=400,INF=2e8;int t,n,m,tot,st,ed,vis[MAXN],d[MAXN],cur[MAXN],map[8];struct Edge{int x,y,cap,flow;};vector <Edge> edges;vector <int> g[MAXN];int min(int a,int b){return a<b?a:b;}void add(int x,int y,int cap){edges.push_back((Edge){x,y,cap,0});edges.push_back((Edge){y,x,0,0});m=edges.size();g[x].push_back(m-2);g[y].push_back(m-1);}bool bfs(){memset(vis,0,sizeof(vis));queue <int> q;q.push(st);d[st]=0;vis[st]=1;while(!q.empty()){int u=q.front();q.pop();for(int i=0;i<g[u].size();++i){Edge &tmp=edges[g[u][i]];if(!vis[tmp.y]&&tmp.cap>tmp.flow){vis[tmp.y]=1;d[tmp.y]=d[u]+1;q.push(tmp.y);}}}return vis[ed];}int dfs(int x,int a){if(x==ed||a==0)return a;int flow=0,f;for(int& i=cur[x];i<g[x].size();++i){Edge& tmp=edges[g[x][i]];if(d[x]+1==d[tmp.y]&&(f=dfs(tmp.y,min(a,tmp.cap-tmp.flow)))>0){tmp.flow+=f;edges[g[x][i]^1].flow-=f;flow+=f;a-=f;if(a==0)break;}}return flow;}int Maxflow(int st,int ed){int flow=0;while(bfs()){memset(cur,0,sizeof(cur));flow+=dfs(st,INF);}return flow;}int main(){scanf("%d",&t);while(t--){scanf("%d",&n);m=tot=0;edges.clear();int i,j,k;st=0,ed=351+n;for(i=0;i<=ed;++i)g[i].clear();for(i=1;i<=n;++i){int d,w;for(j=1;j<=7;++j)scanf("%d",&map[j]);scanf("%d %d",&d,&w);for(j=1;j<=7;++j)if(map[j])for(k=0;k<w;++k)add(i+350,k*7+j,1);tot+=d;add(st,i+350,d);//起点与电影 }for(i=1;i<=50*7;++i)add(i,ed,1);//日期与汇点 if(Maxflow(st,ed)==tot)printf("Yes\n");elseprintf("No\n");}return 0;}
写给自己:入门网络流,dinic还是很容易理解的,打了几道模板题基本会了,至于jyz大神说的 预流推进 还是抽空再学吧;得知过几天开学要考试,整个人都不好了

0 0
原创粉丝点击