题目链接:http://poj.org/problem?id=1459
题目意思让我放弃了好几回,今天终于耐下心来读懂了
就不说题目意思了 看看输入输出:
Sample Input
2 1 1 2 (0,1)20 (1,0)10 (0)15 (1)20 7 2 3 13 (0,0)1 (0,1)2 (0,2)5 (1,0)1 (1,2)8 (2,3)1 (2,4)7 (3,5)2 (3,6)5 (4,2)7 (4,3)5 (4,5)1 (6,0)5 (0)5 (1)2 (3)2 (4)1 (5)4
Sample Output
15 6
2 1 1 2 (0,1)20 (1,0)10 (0)15 (1)20
2 1 1 2依次表示 共两个节点 生产能量的点1个 消费能量的点1个 传递能量的线2条
(0,1)20 (1,0)10 传递能量线 (起点,终点)最大传递的能量
(0)15 产生能量的点 (产生能量的点)产生的最大能量
(1)20 消费能量的点 (消费能量的点)消费的最大能量
最大流算法 构造两个虚拟点 一个代表源点 另一个代表汇点
源点连接产生能量的点 连线的权值为产生的能量
汇点连接消费能量的点 连线的权值为消费的能量
然后求源点到汇点的最大流
解法:EK
代码:
#include <stdio.h> #include <stdlib.h> int que[20000]; int map[150][150]; short flag[150],father[150]; int sta,end,sum; short bfs(int n,int s,int h) { int i,tem,f,min; f=0; min=10000; que[sta]=s; ++sta; for(i=0;i<=n+1;i++) { father[i]=-1; flag[i]=0; } while(sta!=end) { tem=que[end]; ++end; if(map[tem][h]==0) { for(i=0;i<n;++i) { if(map[tem][i]!=0&&flag[i]==0) { que[sta]=i; ++sta; flag[i]=1; father[i]=tem; } } } else { f=1; father[h]=tem; break; } } if(f==1) { for(i=h;father[i]!=-1;i=father[i]) { if(min>map[father[i]][i]) { min=map[father[i]][i]; } } for(i=h;father[i]!=-1;i=father[i]) { map[father[i]][i]-=min; } sum+=min; return 1; } else { return 0; } } int main(int argc, char** argv) { int n,np,nc,m,i,a,b,c,j; char str[50]; while(scanf("%d %d %d %d",&n,&np,&nc,&m)!=EOF) { sum=0; sta=0; end=0; for(i=0;i<=n+1;i++) { for(j=0;j<=n+1;j++) { map[i][j]=0; } } for(i=0;i<m;i++) { scanf("%s",str); sscanf(str,"(%d,%d)%d",&a,&b,&c); map[a][b]=c; } for(i=0;i<np;i++) { scanf("%s",str); sscanf(str," (%d)%d",&a,&b); map[n][a]=b; } for(i=0;i<nc;i++) { scanf("%s",str); sscanf(str," (%d)%d",&a,&b); map[a][n+1]=b; } while(bfs(n,n,n+1)==1) { sta=0; end=0; } printf("%d\n",sum); } return (EXIT_SUCCESS); }