HDU1459 Power Network 【多源多匯最大流】
阿新 • • 發佈:2018-12-19
對於多源多匯問題,解決方法是建立一個超級源點只連線所有源點,建立一個超級匯點只連線所有匯點
這一題節點從0到n-1,可以讓節點的值+1,然後讓0作為超級源點,讓n+1作為超級匯點
對於Init()函式,改變引數讓s=0,讓t=n+1即可
#include<cstdio> #include<cstring> #include<queue> using namespace std; const int INF=1e9; const int maxn=200+10; const int maxm=40000+10; struct Edge{ Edge(){} Edge(int from,int to,int cap,int flow):from(from),to(to),cap(cap),flow(flow){} int from,to,cap,flow; }; struct Dinic{ int n,m,s,t; //結點數,邊數(包括反向弧),源點與匯點編號 Edge edges[maxm]; //邊表 edges[e]和edges[e^1]互為反向弧 int head[maxn],next[maxm]; //鄰接表表頭和next陣列 bool vis[maxn]; //BFS使用,標記一個節點是否被遍歷過 int d[maxn]; //從起點到i點的距離 int cur[maxn]; //當前弧下標 void Init(int n,int s,int t){ this->n=n,this->s=s,this->t=t;//this->n表示Dinic結構體裡的n,避免與函式引數衝突 memset(head,-1,sizeof(head)); m=0; } void AddEdge(int from,int to,int cap){ edges[m]=Edge(from,to,cap,0); next[m]=head[from]; head[from]=m++; edges[m]=Edge(to,from,0,0); next[m]=head[to]; head[to]=m++; } bool BFS(){ memset(vis,0,sizeof(vis)); queue<int> Q; Q.push(s); d[s]=0; vis[s]=true; while(!Q.empty()){ int x=Q.front();Q.pop(); for(int i=head[x]; i!=-1; i=next[i]){ Edge& e=edges[i]; if(!vis[e.to] && e.cap>e.flow){ vis[e.to]=true; 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!=-1;i=next[i]){ Edge& e=edges[i]; if(d[x]+1==d[e.to]&&(f=DFS(e.to,min(a,e.cap-e.flow)))>0){ e.flow+=f; edges[i^1].flow-=f; flow+=f; a-=f; if(a==0) break; } } return flow; } int MaxFlow(){ int flow=0; while(BFS()) { for(int i=s;i<=t;i++) cur[i]=head[i]; flow+=DFS(s,INF); } return flow; } }DC; int main() { int n,np,nc,m; while(scanf("%d%d%d%d",&n,&np,&nc,&m)!=EOF){ DC.Init(n+1,0,n+1);//0為超級源點,n+1為超級匯點 int a,b,d; while(m--){ scanf(" (%d,%d)%d",&a,&b,&d); DC.AddEdge(a+1,b+1,d); } while(np--){ scanf(" (%d)%d",&b,&d); DC.AddEdge(0,b+1,d); } while(nc--){ scanf(" (%d)%d",&a,&d); DC.AddEdge(a+1,n+1,d); } printf("%d\n",DC.MaxFlow()); } return 0; }