题意:n个点(0~n-1),m条边,np个源点,nc个汇点,有各自的流量限制,问同一时刻所有源点到汇点的最大流
思路:最大流,建图,EK
解题方法:新增起始点n,与所有源点相连通;新增终点n+1,与所有汇点相连通,此时就变成求结点n到结点n+1的最大流
注意:这里用的是理解矩阵存的边,刚开始用了vector的邻接表发现超时了
代码如下:
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#define N 110
#define INF 0x3f3f3f3f
typedef long long LL;
using namespace std;
int cap[N][N],flow[N][N],low[N],pre[N];
queue<int>Q;
void init(){
memset(cap,0,sizeof(cap));
memset(flow,0,sizeof(flow));
while(!Q.empty()) Q.pop();
}
void add(int from,int to,int c){
cap[from][to]+=c;
}
int EK(int s,int t){
int max_flow = 0;
while(1){
Q.push(s);
memset(low,0,sizeof(low));
low[s]=INF;
while(!Q.empty()){
int u = Q.front();
Q.pop();
for(int v=0;v<=t;v++){
if(!low[v]&&cap[u][v]>flow[u][v]){
Q.push(v);
low[v]=min(low[u],cap[u][v]-flow[u][v]);
pre[v]=u;
}
}
}
if(low[t]==0) break;
for(int u=t;u!=s;u=pre[u]){
flow[pre[u]][u]+=low[t];
flow[u][pre[u]]-=low[t];
}
max_flow+=low[t];
}
return max_flow;
}
int main(){
int n,np,nc,m,a,b,c;
while(scanf("%d%d%d%d",&n,&np,&nc,&m)!=EOF){
init();
while(m--){
scanf(" (%d,%d)%d",&a,&b,&c);
add(a,b,c);
}
while(np--){
scanf(" (%d)%d",&a,&c);
b=a,a=n;
add(a,b,c);
}
while(nc--){
scanf(" (%d)%d",&a,&c);
b=n+1;
add(a,b,c);
}
printf("%d\n",EK(n,n+1));
}
return 0;
}