这题是一个标准的最大流问题。
题目大意是:有n个点,其中nc个点是发电站,有np个点是用户,其他的是中转站,求最大流。
问题中存在着多源点和多汇点,我们可以把这些源点和汇点当作中转站,在虚拟一个超级源点和超级汇点,EK算法上模版,G++编译器1391MS。
下面是代码:
#include <iostream>
#include <string.h>
#include <queue>
using namespace std;
const int inf = 1<<30;
const int M =105;
int map1[M][M],pre[M],vis[M],n;
int EK()
{
int i,ans=0,now,min1;
queue <int> q;
while(1) //每循环一次找一次增广路
{
memset(pre,-1,sizeof(pre));
memset(vis,0,sizeof(vis));
while(!q.empty())
{
q.pop();
}
q.push(0);
vis[0]=1;
while(!q.empty())
{
now=q.front();
q.pop();
if(now==n+1) //已经搜索到超级汇点 跳出循环
{
break;
}
for(i=0;i<=n+1;i++)
{
if(!vis[i]&&map1[now][i]>0)//如果节点i没被搜索过且节点now到节点i残余流量大于0
{
pre[i]=now; //记录i的前驱节点是now
vis[i]=1; //标记i点已经被访问过
q.push(i); //把i点放入队列进行下一次BFS
}
}
}
if(!vis[n+1])
{
break; //如果BFS完毕没有搜到到节点n+1的增广路,就已经找到最大流 跳出
}
min1=inf;
for(i=n+1;i!=0;i=pre[i])
{
if(map1[pre[i]][i]<min1) //寻找整个增广路上的残余流量的最小值,此为整个增广路的流量
{
min1=map1[pre[i]][i];
}
}
ans+=min1;
for(i=n+1;i!=0;i=pre[i])
{
map1[pre[i]][i]-=min1;//残余流量减少
map1[i][pre[i]]+=min1;//已使用流量增加
}
}
return ans;
}
int main()
{
int np,nc,m,i;
while(cin >> n >> np >> nc >> m)
{
char s;
int u,v,w;
memset(map1,0,sizeof(map1));
for(i=0;i<m;i++)
{
cin >> s >> u >> s >> v >> s >> w;
if(u!=v)
{
map1[u+1][v+1]=w;
}
}
for(i=0;i<np;i++)
{
cin >> s >> v >> s >> w ;
map1[0][v+1]=w;
}
for(i=0;i<nc;i++)
{
cin >> s >> u >> s>> w ;
map1[u+1][n+1]=w;
}
cout << EK() << endl;
}
return 0;
}