1. 程式人生 > >HDU1459 Power Network 【多源多匯最大流】

HDU1459 Power Network 【多源多匯最大流】

對於多源多匯問題,解決方法是建立一個超級源點只連線所有源點,建立一個超級匯點只連線所有匯點

這一題節點從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;
}