题目大意:有发电站,中转站,和用户3种点,发电站和中转站不耗电,用户和中转站不产电。求从发电站到用户的最大电流量。
输入:
2 //点数
1 //发电站数
1 //用户数
2 //边数
(0,1)20 (1,0)10 //边(a,b)c 点a到点b,权值为c
(0)15 //发电站 (a)b 发电站a,产电量b
(1)20 //用户 (a)b 用户a,耗电b
思路用EK算增广路的方法算出最大流,当然,要添加一超级源点和一超级汇点。
//Memory:348KB Time:1188ms
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int N=110;
const int M=20010;
int min(int a,int b)
{
return a<b? a:b;
}
struct Edge
{
int u,v,c,next;
}edge[M];
int path[M],head[N],e;
void add(int u,int v,int c) //添加边得函数
{
edge[++e].u=u;
edge[e].v=v;
edge[e].c=c;
edge[e].next=head[u];
head[u]=e;
}
int BFS(int s,int t) //BFS寻找增广路
{
queue<int> q;
int delta[N];
bool reach[N];
int cur;
memset(delta,0,sizeof delta);
memset(reach,0,sizeof reach);
q.push(s);
delta[s]=0x3f3f3f3f;
reach[s]=1;
while(!q.empty())
{
cur=q.front();
q.pop();
if(cur==t) break;
for(int i=head[cur];i;i=edge[i].next)
{
if(edge[i].c<=0)continue;
if(reach[edge[i].v]) continue;
reach[edge[i].v]=1;
q.push(edge[i].v);
path[edge[i].v]=i;
delta[edge[i].v]=min(delta[cur],edge[i].c);
}
}
return delta[t];
}
int slove(int s,int t)
{
int res=0,delta;
while((delta=BFS(s,t))>0) //若还存在增广路径
{
for(int cur=t;cur-s;cur=edge[path[cur]].u)
{
edge[path[cur]].c-=delta;
}
res+=delta;
}
return res;
}
int main()
{
int n,np,nc,m;
int a,b,c;
while(scanf("%d%d%d%d",&n,&np,&nc,&m)==4)//n+1做超级源,n+2做超级汇
{
e=1;
memset(head,0,sizeof head);
for(int i=1;i<=m;i++) //边的读取
{
scanf(" (%d,%d)%d",&a,&b,&c);
a+=1;
b+=1;
add(a,b,c);
}
for(int i=1;i<=np;i++) //发电站的读取
{
scanf(" (%d)%d",&b,&c);
b+=1;
add(n+1,b,c);
}
for(int i=1;i<=nc;i++) //用户的读取
{
scanf(" (%d)%d",&a,&c);
a+=1;
add(a,n+2,c);
}
printf("%d\n",slove(n+1,n+2)); //计算超级源到超级汇的最大流
}
}