POJ 3281 网络流 拆点保证本身只匹配一对食物和饮料
Posted lighten-up-belief
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ 3281 网络流 拆点保证本身只匹配一对食物和饮料相关的知识,希望对你有一定的参考价值。
如何建图?
最开始的问题就是,怎么表示一只牛有了食物和饮料呢?
后来发现可以先将食物与牛匹配,牛再去和饮料匹配,实际上这就构成了三个层次。
起点到食物层边的容量是1,食物层到奶牛层容量是1,奶牛层到饮料层容量是1,饮料层到终点容量是1。
但是后来发现有一组hack数据:
2 3 3
3 3 1 2 3 1 2 3
3 3 1 2 3 1 2 3
我们发现一头奶牛居然吃了多个套餐,所以要解决这个只需要将自己与自己建立一条容量是1的边就行了。
#include <cstdio> #include <cstring> #include <stack> using namespace std; #define sc scanf #define pt printf #define maxe 40960 #define maxv 405 #define maxn 1000 #define mll long long const int inf = 0x3f3f3f3f; int mn(int a,int b) return a<b?a:b; int s,t, N,F,D; typedef struct ed int v,w,cap,flow; ed; ed e[maxe]; int head[maxv],nxt[maxe],tot,dis[maxv]; void init() tot = 0 ; memset(head,-1,sizeof(head)); void add(int u,int v,int cap,int flow) e[tot].v=v; e[tot].cap=cap; e[tot].flow=flow; nxt[tot]=head[u]; head[u]=tot++; e[tot].v=u; e[tot].cap=flow; e[tot].flow=0; nxt[tot]=head[v]; head[v]=tot++; int dfs(int u,int exp) if(exp==0||u==t) return exp; int i,v,flow=0,tmp; for(i=head[u];i!=-1;i=nxt[i]) v=e[i].v; //pt("u=%d,v=%d\n",u,v); if(dis[v]==dis[u]+1) tmp = dfs(v,mn(e[i].cap-e[i].flow,exp)); if(tmp==0) continue; // pt("u=%d,v=%d,tmp=%d\n",u,v,tmp); e[i].flow += tmp; e[i^1].flow -= tmp; exp-=tmp; flow+=tmp; if(exp==0) break; //pt("wt\n"); if(flow==0) dis[u]=inf; return flow; stack<int> q; int main() freopen("in.txt","r",stdin); while(~sc("%d%d%d",&N,&F,&D)) //pt("OK\n"); int i,j,ans=0,u,v,tt,FF,DD; init(); s=0,t=1+2*N+F+D; // pt("OK\n"); // F使用1-F N使用(F+1 - F+N)(F+1 + N - F+ 2*N) D使用 F+2*N+1 - F+2*N+D for(i=1;i<=F;++i) add(0,i,1,0); for(i=F+2*N+1;i<=F+2*N+D;++i) add(i,t,1,0); for(i=F+1;i<=F+N;++i) add(i,i+N,1,0); //pt("OK\n"); for(i=1;i<=N;++i) sc("%d%d",&FF,&DD); for(j=1;j<=FF;++j) sc("%d",&tt); add(tt,F+i,1,0); for(j=1;j<=DD;++j) sc("%d",&tt); add(F+N+i,F+2*N+tt,1,0); //pt("OK\n"); while(1) //BFS建立层次图 memset(dis,inf,sizeof(dis)); dis[s]=0; while(!q.empty()) q.pop(); q.push(s); while(!q.empty()) u=q.top(); q.pop(); for(i=head[u];i!=-1;i=nxt[i]) if(e[i].cap - e[i].flow <= 0) continue; v = e[i].v; if(dis[u]+1<dis[v]) dis[v] = dis[u] +1; //pt("BFS: u=%d,v=%d\n",u,v); if(v==t) break; q.push(v); if(dis[t]==inf) break; //DFS进行增广 tt=dfs(0,inf); if(tt==0) break; else ans+=tt; //pt("tt=%d\n",tt); pt("%d\n",ans); return 0;
以上是关于POJ 3281 网络流 拆点保证本身只匹配一对食物和饮料的主要内容,如果未能解决你的问题,请参考以下文章