题目链接:poj 1459
参考题意博客:https://blog.csdn.net/huangshuai147/article/details/51179586
Sample Input
2 1 1 2 (0,1)20 (1,0)10 (0)15 (1)20 7 2 3 13 (0,0)1 (0,1)2 (0,2)5 (1,0)1 (1,2)8 (2,3)1 (2,4)7 (3,5)2 (3,6)5 (4,2)7 (4,3)5 (4,5)1 (6,0)5 (0)5 (1)2 (3)2 (4)1 (5)4
这题目又臭又长,参考此博客题意:
前四个数分别表示,m个点,np个发电站,nc个用户,n条边
接下去是n条边 ------(u,v)w,w表示边(u,v)的最大流量;
np个发电站---(u)w,w表示发电站u能提供的最大流量;
nc个用户的信息(v)w,w表示每个用户v能接受的最大流量。
解题思路:对于这道题我们建立一个超级源点和超级汇点,所谓超级源点指的是所有发电站发电量的总和,超级汇点指的是所有用户接受的电量总和,对此我们建立0为超级源点,m+1为超级汇点,其余的按输入存储就行了,还有一个题目的点是从0开始的,而我们没有-1的点来做超级源点,故我们把题目输入的点都往后移一位。
///简单网络流变形
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
typedef long long LL;
#define INF 0x3f3f3f3f
const int maxn=105;
int capacity[maxn][maxn];
int flow[maxn];
int pre[maxn];
int n,m;
queue <int> myqueue;
int BFS(int src,int des)
{
while(!myqueue.empty())
myqueue.pop();
memset(pre,-1,sizeof(pre));
pre[src]=0;
flow[src]=INF;
myqueue.push(src);
while(!myqueue.empty())
{
int index=myqueue.front();
myqueue.pop();
if(index==des) break;
for(int i=0;i<=des;i++) ///从源点到目标循环
{
if(i!=src&&capacity[index][i]>0&&pre[i]==-1)
{
pre[i]=index;
flow[i]=min(capacity[index][i],flow[index]);
myqueue.push(i);
}
}
}
if(pre[des]==-1) return -1;
else return flow[des];
}
int maxFlow(int src,int des) ///EK模板
{
int increase=0;
int sumflow=0;
while((increase=BFS(src,des))!=-1)
{
int k=des;
while(k!=src)
{
int last=pre[k];
capacity[last][k]-=increase;
capacity[k][last]+=increase;
k=last;
}
sumflow+=increase;
}
return sumflow;
}
int main()
{
int a,b;
while(~scanf("%d%d%d%d",&n,&a,&b,&m))
{
memset(capacity,0,sizeof(capacity));
int u,v,w;
for(int i=1;i<=m;i++)
{
scanf(" (%d,%d)%d",&u,&v,&w);
if(u!=v) capacity[++u][++v]=w;
}
for(int i=1;i<=a;i++)
{
scanf(" (%d)%d",&u,&w);
capacity[0][++u]=w; ///因为发电站的点可以是0,而我们希望0作为超级源点,故都往后移一位
}
for(int i=1;i<=b;i++)
{
scanf(" (%d)%d",&v,&w);
capacity[++v][n+1]=w;
}
printf("%d\n",maxFlow(0,n+1));
}
return 0;
}