/*这个题目是网络流的经典模板题;我刚刚接触网络流,为了熟悉模板我用这个题目写了三种模板。
题意:
给几个发电站,给几个消耗站,再给几个转发点。
发电站只发电,消耗站只消耗电,转发点只是转发电,再给各个传送线的传电能力。
问你消耗站能获得的最多电是多少。
思路:增加一个超级源点,和超级汇点。。把所给的发电站都和超级源点相连,把所给的消耗战都和超级汇点相连。。
这样就可以用网络流的最大流来做了。。*/
/*#include <iostream>
#include <queue>
using namespace std;
const int N = 210;
const int INF = 0x7FFFFFFF;
int n,np,nc,m,temp;
int map[N][N],path[N],flow[N],start,end;
queue<int> q;
int bfs()
{
int i,t;
while(!q.empty()) q.pop();
memset(path,-1,sizeof(path));
path[start]=0,flow[start]=INF;
q.push(start);
while(!q.empty())
{
t=q.front();
q.pop();
if(t==end) break;
for(i=0;i<=temp;i++)//这里是点的循环。。
{
if(i!=start && path[i]==-1 && map[t][i])
{
flow[i]=flow[t]<map[t][i]?flow[t]:map[t][i];
q.push(i);
path[i]=t;
}
}
}
if(path[end]==-1) return -1;
return flow[temp]; //一次遍历之后的流量增量
}
int Edmonds_Karp()
{
int max_flow=0,step,now,pre;
while((step=bfs())!=-1)
{ //找不到增路径时退出]
max_flow+=step;
now=end;
while(now!=start)
{
pre=path[now];
map[pre][now]-=step; //更新正向边的实际容量....残留网络=容量网络-流量网络
map[now][pre]+=step; //添加反向边
now=pre;
}
}
return max_flow;
}
int main()
{
int i,u,v,cost;
char c;
while(scanf("%d %d %d %d",&n,&np,&nc,&m)!=EOF)
{
memset(map,0,sizeof(map));
for(i=0;i<m;i++)
{
while(c=getchar())
{
if(c=='(')
break;
}
cin>>u;
getchar();
cin>>v;
getchar();
cin>>cost;
map[u+1][v+1]=cost;
}
temp=n+1;
n+=2;
m+=(np+nc);
for(i=0;i<np;i++)
{
while(c=getchar())
{
if(c=='(')
break;
}
cin>>u;
getchar();
cin>>cost;
map[0][u+1]=cost;
}
for(i=0;i<nc;i++)
{
while(c=getchar())
{
if(c=='(')
break;
}
cin>>u;
getchar();
cin>>cost;
map[u+1][temp]=cost;
}
start=0,end=temp;
printf("%d\n",Edmonds_Karp());
}
return 0;
}*/
//下面是用ISPA写的:
#include <iostream>
#include <queue>
#include<algorithm>
using namespace std;
#define inf 999999999
const int N=210;
int n,np,nc,m,temp;
int s,t,dis[N],pre[N],gap[N],flow[N][N];
struct edge
{
int v,w;
edge *next,*rev;
edge(){next=0;}
edge(int vv,int ww,edge *e){v=vv;w=ww;next=e;}
}*adj[N],*path[N],*e;
int min(int x,int y)
{
if(x>y)
return y;
else
return x;
}
void insert(int u,int v,int w)
{
edge *p=new edge(v,w,adj[u]);
adj[u]=p;
edge *q=new edge(u,0,adj[v]);
adj[v]=q;
p->rev=q;
q->rev=p;
}
void bfs()
{
memset(dis,0x7f,sizeof(dis));
memset(gap,0,sizeof(gap));
queue<int> q;
dis[t]=0;
gap[0]=1;
q.push(t);
while(q.size())
{
int x=q.front();
q.pop();
for(e=adj[x];e;e=e->next)
{
if(e->rev->w==0||dis[e->v]<t)
continue;
dis[e->v]=dis[x]+1;
++gap[dis[e->v]];
q.push(e->v);
}
}
}
int ISAP()
{
memset(dis,0,sizeof(dis));
memset(gap,0,sizeof(gap));
//bfs();
int ans=0,u=s,d;
while(dis[s]<=t)
{
if(u==t)
{
int minflow=-1u>>1;
for(e=path[u];u!=s;e=path[u=pre[u]])
minflow=min(minflow,e->w);
for(e=path[u=t];u!=s;e=path[u=pre[u]])
{
e->w-=minflow;
e->rev->w+=minflow;
flow[pre[u]][u]+=minflow;
flow[u][pre[u]]-=minflow;
}
ans+=minflow;
}
for(e=adj[u];e;e=e->next)
if(e->w>0&&dis[u]==dis[e->v]+1)
break;
if(e)
{
pre[e->v]=u;
path[e->v]=e;
u=e->v;
}
else
{
if(--gap[dis[u]]==0)
break;
for(d=t,e=adj[u];e;e=e->next)
if(e->w>0)
d=min(d,dis[e->v]);
dis[u]=d+1;
++gap[dis[u]];
if(u!=s)
u=pre[u];
}
}
return ans;
}
int main()
{
int i,U,V,cost;
char c;
while(scanf("%d %d %d %d",&n,&np,&nc,&m)!=EOF)
{
memset(adj,0,sizeof(adj));//这句要记得加哦。。
for(i=0;i<m;i++)
{
while(c=getchar())
{
if(c=='(')
break;
}
cin>>U;
getchar();
cin>>V;
getchar();
cin>>cost;
insert(U+1,V+1,cost);
}
temp=n+1;
n+=2;
m+=(np+nc);
for(i=0;i<np;i++)
{
while(c=getchar())
{
if(c=='(')
break;
}
cin>>U;
getchar();
cin>>cost;
insert(0,U+1,cost);
}
for(i=0;i<nc;i++)
{
while(c=getchar())
{
if(c=='(')
break;
}
cin>>U;
getchar();
cin>>cost;
insert(U+1,temp,cost);
}
s=0,t=temp;
printf("%d\n",ISAP());
}
return 0;
}
//下面是用DICNIC做的:
/*
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 5005
#define M 25000//这里的数组开小了,,导致我找了一个多小时。。晕啊。。
#define inf 999999999
int n,np,nc,m,temp;
using namespace std;
int s,t,num,adj[N],dis[N],q[N];
int min(int a,int b)
{
if(a>b)
return b;
else
return a;
}
struct edge
{
int v,w,pre;
}e[M];
/*void insert(int u,int v,int w)
{
e[num]=(edge){v,w,adj[u]};
adj[u]=num++;
e[num]=(edge){u,0,adj[v]};
adj[v]=num++;
}
void insert(int u,int v,int w) //上面的insert可以写成下面这种。。
{
e[num].v=v;
e[num].w=w;
e[num].pre=adj[u];
adj[u]=num++;
e[num].v=u;
e[num].w=0;
e[num].pre=adj[v];
adj[v]=num++;
}
int bfs()
{
int i,x,v,tail=0,head=0;
memset(dis,0,sizeof(dis));
dis[s]=1;
q[tail++]=s;
while(head<tail)
{
x=q[head++];
for(i=adj[x];i!=-1;i=e[i].pre)
if(e[i].w&&dis[v=e[i].v]==0)
{
dis[v]=dis[x]+1;
if(v==t)
return 1;
q[tail++]=v;
}
}
return 0;
}
int dfs(int s,int limit)
{
if(s==t)
return limit;
int i,v,tmp,cost=0;
for(i=adj[s];i!=-1;i=e[i].pre)
if(e[i].w&&dis[s]==dis[v=e[i].v]-1)
{
tmp=dfs(v,min(limit-cost,e[i].w));
if(tmp>0)
{
e[i].w-=tmp;
e[i^1].w+=tmp;
cost+=tmp;
if(limit==cost)
break;
}
else dis[v]=-1;
}
return cost;
}
int Dinic()
{
int ans=0;
while(bfs())
ans+=dfs(s,INT_MAX);
return ans;
}
int main()
{
int U,V,co;//主函数的变量不要和上面的函数重复了。。
char c;
while(cin>>n>>np>>nc>>m)
{
memset(adj,-1,sizeof(adj));//一定要记得初始化。。
num=0;
while(m--)
{
while(c=getchar())
{
if(c=='(')
break;
}
cin>>U;
getchar();
cin>>V;
getchar();
cin>>co;
insert(U+1,V+1,co);
}
temp=n+1;
n+=2;
m+=(np+nc);
s=0;
t=temp;
while(np--)
{
while(c=getchar())
{
if(c=='(')
break;
}
cin>>U;
getchar();
cin>>co;
insert(0,U+1,co);
}
while(nc--)
{
while(c=getchar())
{
if(c=='(')
break;
}
cin>>U;
getchar();
cin>>co;
insert(U+1,temp,co);
}
cout<<Dinic()<<endl;
}
return 0;
}*/