天天看點

網絡流 EK增廣路算法之二

//多源多彙網絡流      
//poj 1459 Power Network      
#include<iostream>            //參考poj8 1273 Drainage Ditches      
#include<queue>      
using namespace std;      
#define inf 0x7fffffff      
int flow[102][102],cap[102][102],a[102],p[102],s,t,f;      
int n,np,nc,m,u,v,z;      
void ek()      
{      
queue<int> col;      
memset(flow,0,sizeof(flow));      
f=0;      
while(1)      
{      
memset(a,0,sizeof(a));      
a[s]=inf;      
col.push(s);      
while(!col.empty())      
{      
int u=col.front();col.pop();      
for(int i=0;i<=n+1;++i)        //與poj8 1273 不同,注意i的變化範圍      
if(!a[i]&&cap[u][i]>flow[u][i])      
{      
a[i]=min(a[u],cap[u][i]-flow[u][i]);      
p[i]=u;      
col.push(i);      
}      
}      
if(a[t]==0)      
break;      
for(int i=t;i!=s;i=p[i])      
flow[p[i]][i]+=a[t],flow[i][p[i]]-=a[t];      
f+=a[t];      
}      
cout<<f<<endl;      
}      
int main()      
{      
while(scanf("%d%d%d%d",&n,&np,&nc,&m)!=EOF)      
{      
s=0;t=n+1;        //超級源點,彙點      
memset(cap,0,sizeof(cap));      
while(m--)      
{      
scanf(" (%d,%d)%d",&u,&v,&z);      
cap[u+1][v+1]+=z;    //初始時結點的下标從0到n-1,+1後從1到n,添加超級源點,彙點後從0到n+1      
}      
while(np--)      
{      
scanf(" (%d)%d",&u,&z);      
cap[s][u+1]=z;      
}      
while(nc--)      
{      
scanf(" (%d)%d",&u,&z);        //這裡不能是scanf(" (%d)%d ",&u,&z);      
cap[u+1][t]=z;      
}      
ek();      
}      
return 0;      
}      
//在圖中添加1個源點s和彙點t,将s和每個發電站(類型為p的結點)相連,邊的權值是發電站能提供的最大流量;      
//将每個使用者和t相連,邊的權值是每個使用者(類型為c的結點)能接受的最大流量。進而轉化成了一般的最大網絡流問題,然後求解。