//题目类型:最大流(多源点、多汇点)构图简单题
//解题思路:分别添加超级源点和超级汇点,使用ISAP算法实现,另外本题的输入与输出也应该特别学习
#include <iostream>
#include <queue>
//#include <conio.h>
using namespace std;
#define arraysize 205
int maxData = 0x7fffffff;
int capacity[arraysize][arraysize]; //残留网络,初始化为原图
int pre[arraysize]; //前驱
int num[arraysize]; //num[i]表示标号为i的顶点数有多少
int d[arraysize]; //各结点的标号
int n,np,nc,m;
void init(int src,int des) //BFS计算标号,汇点t标号为0
{
int i,j;
queue<int> myqueue;
myqueue.push(des);
memset(num,0,sizeof(num));
//memset(d,1,sizeof(d));
for(i=0;i<n+2;++i) //其余点的距离标号为无穷大
d[i] = maxData;
d[des] = 0; //汇点的距离标号为0
num[0] = 1;
int frontint;
while(!myqueue.empty())
{
frontint = myqueue.front();myqueue.pop();
for(i=0;i<n+2;++i)
{
if(d[i]>=n+2 && capacity[i][frontint]>0) //此处要特别注意,通过frontint的值改变其他的距离标号
{
d[i] = d[frontint]+1;
myqueue.push(i);
num[d[i]]++;
}
}
}
}
int findarc(int t) //查找允许弧
{
int i,j;
for(i=0;i<n+2;++i)
{
if(capacity[t][i]>0 && d[t]==d[i]+1) return i;
}
return -1;
}
int relabel(int t) //重新标号
{
int i,j;
//int mm = INT_MAX;
int mm = maxData;
for(i=0;i<n+2;++i)
{
if(capacity[t][i]>0) mm = min(mm,d[i]+1);
}
return mm==maxData?(n+2):mm;
}
int maxFlow(int src,int des)
{
int sumflow = 0;
int delta;
int i=src; //初始化为源点
int j;
memset(pre,-1,sizeof(pre));
while(d[src]<n+2)
{
j = findarc(i);
if(j>=0)
{
pre[j] = i;
i = j; //从前往后找
if(i==des) //找到了增广路径
{
delta = maxData;
for (i=des;i!=src;i=pre[i]) delta=min(delta,capacity[pre[i]][i]); //求的增广路径的可增流量
for (i=des;i!=src;i=pre[i]) capacity[pre[i]][i] -= delta, capacity[i][pre[i]] += delta; //修改残留网络
sumflow += delta;
}
}
else
{
int x = relabel(i);
num[x]++;
num[d[i]]--;
if(num[d[i]]==0) return sumflow; //间隙优化
d[i] = x;
if(i!=src) i =pre[i];
}
}
return sumflow;
}
int main()
{
//freopen("1.txt","r",stdin);
int i,j;
int start,end,weight;
char tempchar;
//本题的输入输出要特别注意
while(cin>>n>>np>>nc>>m)
{
memset(capacity,0,sizeof(capacity));
//定义一个字符类型来处理题目中的括号
for(i=0;i<m;++i)
{
cin>>tempchar>>start>>tempchar>>end>>tempchar>>weight;
capacity[start][end] = weight;
}
for(i=0;i<np;++i)
{
cin>>tempchar>>end>>tempchar>>weight;
capacity[n+1][end]= weight; //n+1代表超级源点
}
for(i=0;i<nc;++i)
{
cin>>tempchar>>start>>tempchar>>weight;
capacity[start][n]= weight; //n代表超级终点
}
init(n+1,n); //初始化标号
int result = maxFlow(n+1,n); // 计算最大流
cout<<result<<endl;
}
/*采取scanf的方式读取
while(scanf("%d%d%d%d",&n,&np,&nc,&m)!=EOF)
{
memset(r,0,sizeof(r));
for(i=1;i<=m;i++)
{
scanf(" (%d,%d)%d",&a,&b,&z);
r[a][b]=z;
}
for(i=1;i<=np;i++)
{
scanf(" (%d)%d",&a,&z);
r[n][a]=z;
}
for(i=1;i<=nc;i++)
{
scanf(" (%d)%d",&a,&z);
r[a][n+1]=z;
}
init(n+1,n);
printf("%d\n",maxFlow(n+1,n));
}*/
//getch();
return 0;
}