1. 程式人生 > >poj1149PIGS——網絡最大流

poj1149PIGS——網絡最大流

tmp http 順序 can n) stream truct pri amp

題目:http://poj.org/problem?id=1149

不把豬圈當做點,而把顧客當作點,把豬當作邊權(流量);

因為豬圈中的豬可流動,所以共用一個豬圈的人互相連邊;

註意應該連成鏈的形式,來保證先後順序。

代碼如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
queue<int>q;
int m,n,s[1005],head[150],ct=1,cur[150],hd[1005],inf=1e9,d[150
],ans; bool sid[150][150]; struct N{ int to,next,w; N(int t=0,int n=0,int ww=0):to(t),next(n),w(ww) {} }edge[25000]; bool in[150]; void add(int x,int y,int z) { sid[x][y]=1;sid[y][x]=1; edge[++ct]=N(y,head[x],z);head[x]=ct; edge[++ct]=N(x,head[y],0);head[y]=ct; } int fd(int x,int y) {
for(int i=head[y];i;i=edge[i].next)//此處為有向邊,所以應找y邊集中連到x的邊! if(edge[i].to==x)return i; return 0; } bool bfs() { memset(d,0,sizeof d); while(q.size())q.pop(); d[0]=1;q.push(0); while(q.size()) { int x=q.front();q.pop(); for(int i=head[x];i;i=edge[i].next) {
int u=edge[i].to; if(!d[u]&&edge[i].w) { d[u]=d[x]+1; q.push(u); } } } return d[n+1]; } int dfs(int x,int f) { if(x==n+1)return f; int res=0; for(int i=cur[x];i;i=edge[i].next) { int u=edge[i].to; if(d[u]==d[x]+1&&edge[i].w) { int tmp=dfs(u,min(edge[i].w,f-res)); edge[i].w-=tmp; edge[i^1].w+=tmp; res+=tmp; if(edge[i].w)cur[x]=i; if(res==f)return f; } } if(!res)d[x]=0; return res; } int main() { scanf("%d%d",&m,&n); for(int i=1;i<=m;i++) scanf("%d",&s[i]); for(int i=1;i<=n;i++) { int k,x; scanf("%d",&k); for(int j=1;j<=k;j++) { scanf("%d",&x); if(!hd[x]&&!in[i])hd[x]=i,in[i]=1,add(0,i,s[x]); else if(!hd[x]&&in[i]) { hd[x]=i; int e=fd(i,0); edge[e].w+=s[x]; // edge[e^1].w-=s[x];//!!! } // if(!hd[x])hd[x]=i,add(0,i,s[x]); if(hd[x]) { if(!sid[hd[x]][i])//免重 add(hd[x],i,inf); hd[x]=i;//!!!成鏈 } } scanf("%d",&x); add(i,n+1,x); } while(bfs()) { for(int i=0;i<=n+1;i++)cur[i]=head[i]; ans+=dfs(0,inf); } printf("%d",ans); return 0; }

poj1149PIGS——網絡最大流