/*
邻接矩阵实现ISAP
间隙优化,current
*/
// include file
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cctype>
#include <ctime>
#include <iostream>
#include <sstream>
#include <fstream>
#include <iomanip>
#include <bitset>
#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <set>
#include <list>
#include <functional>
using namespace std;
// typedef
typedef long long LL;
typedef unsigned long long ULL;
typedef __int64 Bint;
//
#define read freopen("in.txt","r",stdin)
#define write freopen("out.txt","w",stdout)
#define FORi(a,b,c) for(int i=(a);i<(b);i+=c)
#define FORj(a,b,c) for(int j=(a);j<(b);j+=c)
#define FORk(a,b,c) for(int k=(a);k<(b);k+=c)
#define FORp(a,b,c) for(int p=(a);p<(b);p+=c)
#define FORii(a,b,c) for(int ii=(a);ii<(b);ii+=c)
#define FORjj(a,b,c) for(int jj=(a);jj<(b);jj+=c)
#define FORkk(a,b,c) for(int kk=(a);kk<(b);kk+=c)
#define FF(i,a) for(int i=0;i<(a);i++)
#define FFD(i,a) for(int i=(a)-1;i>=0;i--)
#define Z(a) (a<<1)
#define Y(a) (a>>1)
const double eps = 1e-6;
const double INFf = 1e10;
const int INFi = 1000000000;
const double Pi = acos(-1.0);
template<class T> inline T sqr(T a){return a*a;}
template<class T> inline T TMAX(T x,T y)
{
if(x>y) return x;
return y;
}
template<class T> inline T TMIN(T x,T y)
{
if(x<y) return x;
return y;
}
template<class T> inline void SWAP(T &x,T &y)
{
T t = x;
x = y;
y = t;
}
template<class T> inline T MMAX(T x,T y,T z)
{
return TMAX(TMAX(x,y),z);
}
// code begin
#define MAXN 110
int N,NP,NC,M;
int source,sink;
// graph and flow
int G[MAXN][MAXN],F[MAXN][MAXN];
// predecessor list
int pi[MAXN];
int CurrentNode[MAXN];
int que[MAXN]; //BFS用
int d[MAXN]; // 到汇点的距离
int numbs[MAXN]; // 每层顶点个数
void rev_BFS()
{
int head(0),tail(0);
memset(numbs,0,sizeof(numbs));
// initially, all d[i] = n;
FORi(1,N+1,1)
{
d[i] = N;
numbs[d[i]]++; // numbs记录每层顶点个数
}
// start from the sink
numbs[N]--;
d[sink] = 0;
numbs[ d[sink] ]++;
que[++tail] = sink;
while(head!=tail)
{
int cur = que[++head];
// check all adjcent nodes
FORj(1,N+1,1)
{
if(d[j]<N || G[j][cur]==0) continue;
// j is reached first time
// put it into queue
que[++tail] = j;
// update distance function
numbs[N]--;
d[j] = d[cur]+1;
numbs[d[j]]++;
}
}
}
// augment the flow using predecessor list pi[]
int Augment()
{
int i,j,tmp,width = INFi;
// find the capacity of the path
for(i=sink,j=pi[i];i!=source;i=j,j=pi[i])
{
tmp = G[j][i];
if(tmp<width) width = tmp;
}
// augmenting
for(i=sink,j=pi[i];i!=source;i=j,j=pi[i])
{
G[j][i]-=width; //F[j][i]+=width;
G[i][j]+=width; //F[i][j]-=width;
}
return width;
}
// relabel and backtrack
int Retreat(int &cur)
{
int tmp;
int mind(N-1);
FORj(1,N+1,1)
{
if(G[cur][j]>0 && d[j]<mind)
mind = d[j];
}
tmp = d[cur];
// relabel
numbs[ d[cur] ]--;
d[cur] = 1+mind;
numbs[ d[cur] ]++;
// backtrack
if(cur!=source) cur = pi[cur];
//
return numbs[ tmp ];
}
// Main procedure
int MaxFlow_ISAP()
{
int flow(0);
rev_BFS(); //先吧所有顶点到sink的距离求出来
//把所有点的当前边都设置成1
FORi(1,N+1,1)
CurrentNode[i] = 1;
//
int st = source;
// the main cycle (while the source is not "far" from the sink)
while(d[source]<N)
{
// start searching an admissible arc from the current arc
int ds;
for(ds=CurrentNode[st];ds<=N;ds++)
{
if(G[st][ds]>0 && d[st]==d[ds]+1)
break;
}
// if the admissible arc is found
if(ds<=N)
{
CurrentNode[st] = ds; // 把ds当成当前边的点
pi[ds] = st; // ds is reachable from st;
st = ds; // go forward
if(st==sink)
{
flow+=Augment();
st = source;
}
}
else
{
CurrentNode[st] = 1;
if( Retreat(st) == 0 )
break;
}
}
return flow;
}
int main()
{
read;
write;
int a,b,c;
char rt[4];
while(scanf("%d %d %d %d",&N,&NP,&NC,&M)!=-1)
{
memset(G,0,sizeof(G));
memset(F,0,sizeof(F));
source = N+1;
sink = N+2;
getchar();
while(M--)
{
scanf(" (%d,%d)%d",&a,&b,&c);
//printf("边 %d %d %d\n",a,b,c);
G[++a][++b]=c;
}
//为了找最大流,我们要添加一个新的源点和汇点 N和N+1
//接下来是源点
while(NP--)
{
scanf(" (%d)%d",&b,&c);
//printf("源点 %d %d\n",b,c);
G[N+1][++b] = c;
}
//接下来是汇点
while(NC--)
{
scanf(" (%d)%d",&a,&c);
G[++a][N+2] = c;
}
N+=2;
// 图建好了
printf("%d\n",MaxFlow_ISAP());
}
return 0;
}