【網路流專題3】 結點流量
阿新 • • 發佈:2018-11-01
Ahead
11.1.2018
例題
poj 3281
割點法
即點權割成兩個點,類似經過一個城池有入城和出城兩個門
對於本題只要源點向食物,食物向牛1,牛1向牛2 牛2向飲料,飲料向匯點分別見一條1的邊,其中牛1牛2指同一頭牛的割點 然後食物與飲料向牛的建邊是根據題目給定建。最後跑一個最大流
樣例的建圖
程式碼
#include <iostream> #include <cstdlib> #include <cstdio> #include <cstring> #include <queue> using namespace std; const int s = 1000,t = 1001; const int N = 40000,inf = 0x3f3f3f3f; int n,f,d; int to[N<<1],nxt[N<<1],last[N],w[N<<1],len=1; inline void ins(int x,int y,int c) { to[++len]=y,nxt[len]=last[x],w[len]=c,last[x]=len; } int h[N]; bool vis[N]; bool bfs() { memset(h,0,sizeof(h)); queue <int> q; vis[s]=1; q.push(s); h[s]=1; while(!q.empty()) { int x = q.front(); q.pop(); vis[x]=0; for(int k=last[x]; k; k=nxt[k]) { int y=to[k]; if(w[k] && !h[y]) { h[y] = h[x] + 1 ; if(!vis[y]) { vis[y]=1; q.push(y); } } } } return h[t]!=0; } int dfs(int x,int flow) { if(x==t) return flow; int res=flow; for(int k=last[x]; k; k=nxt[k]) { int y=to[k]; if(w[k] && h[y] == h[x]+1) { int t = dfs(y,min(w[k],res)); w[k]-=t; w[k^1]+=t; res-=t; if(res==0) break; } } if(res==flow) h[x]=0; return flow-res; } inline int dinic() { int maxflow=0; while(bfs()) { int tmp = dfs(s,inf); while(tmp) { maxflow += tmp; tmp = dfs(s,inf); } } return maxflow; } int main() { int x,y,z; scanf("%d%d%d",&n,&f,&d); //build for(int i=1; i<=f; ++i) ins(s,i,1),ins(i,s,0); for(int i=1; i<=d; ++i) ins(f+n+n+i,t,1),ins(t,f+n+n+i,0); for(int i=1; i<=n; ++i) ins(f+i,f+n+i,1),ins(f+n+i,f+i,0); for(int i=1; i<=n; ++i) { scanf("%d%d",&x,&y); for(int j=1; j<=x; ++j) { scanf("%d",&z); ins(z,i+f,1); ins(i+f,z,0); } for(int j=1; j<=y; ++j) { scanf("%d",&z); ins(i+n+f,f+n+n+z,1); ins(f+n+n+z,f+n+i,0); } } printf("%d\n",dinic()); return 0; }