//题目类型:最大流(多源点、多汇点)构图简单题 //解题思路:分别添加超级源点和超级汇点,使用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; }