poj1459多源点多汇点最大流

来源:互联网 发布:淘宝网下载2016新版 编辑:程序博客网 时间:2024/05/16 08:34

题目链接:http://poj.org/problem?id=1459

题意:有许多发电厂,需求电的地方(就说耗电场吧)和一些中转站,要求出各个耗电场耗电之和,并使之最大。其中边上的权值为能流通的最大电量。

题目解析:这道题目也是很简单的最大流题目,只需要添加一个总的源点和一个总的汇点,然后从总源点到子源点边上的权值为子源点的发电量,从汇点到总汇点边上的权值为子汇点的需求电量。就转化成了单源点单汇点的最大流问题了。刚学网络流,不成熟的SAP算法,代码如下:

#include<iostream>#include<cstring>#include<cstdio>using namespace std;#define MAXN  205#define INS 0xfffffff#define clr(arr) memset(arr,0,sizeof(arr))int map[MAXN][MAXN];int cate[MAXN],index[MAXN],gap[MAXN];int pre[MAXN],q[MAXN];bool vis[MAXN],flag;int minres;void init_gap_bfs(int n){int v,start,end,size = 100; start = end = 0; index[0] = 1; clr(vis); clr(q);q[start] = n; vis[n] = true; end++;while(start != end){v = q[start]; for(int i = 0;i <= n;++i){if((!vis[i] ) && map[i][v] > 0){vis[i] = true;gap[i] = gap[v] + 1;index[ gap[i] ]++;q[end] = i; end = (end+1)%size;}}start = (start+1)%size;}}bool dfs(int k,int n){int m = minres;for(int i = 0;i <= n;++i)if(gap[k] - gap[i] ==1 && map[k][i] > 0){pre[i] = k; minres = min(minres,map[k][i]);if(i == n || dfs(i,n)) return true;minres = m;}index[ gap[k] ]--; index[ gap[k]+1 ]++; if(index[ gap[k] ] == 0)   flag = true;gap[k] += 1; return false;}int SAP(int b,int n){flag = false;int maxflow = 0;while(!flag){ clr(pre); pre[0] = -1; minres = INS;if(!dfs(b,n)) continue; int i = n; maxflow += minres;while(pre[i] != -1){map[ pre[i] ][i] -= minres; map[i][ pre[i] ] += minres;i = pre[i];}}   return maxflow;}int main(){//freopen("1.txt","r",stdin);int n,np,nc,m,b,e,v,p;while(~scanf("%d%d%d%d",&n,&np,&nc,&m)){clr(cate); clr(map); clr(index); clr(gap);for(int i = 0;i < m;++i){scanf(" (%d,%d)%d ",&b,&e,&v);b++; e++;map[b][e] += v;}for(int i = 0;i < np + nc;++i){scanf(" (%d)%d ",&p,&v);  p++; if(i < np) cate[p] += v;else cate[p] -=v;}for(int i =1;i <= n;++i){if(cate[i] > 0) map[0][i] = cate[i];if(cate[i] < 0) map[i][n+1] = -cate[i];}init_gap_bfs(n+1);printf("%d\n",SAP(0,n+1));}return 0;}

下面是用间隙优化和弧优化的代码,不过弧优化没写好,每次当从k点找不到增广路的时候,更新从k点到汇点的距离,是自加1,不是找所有孩子里汇点最近的加1,不知道怎么处理的,提交结果竟然时间一点也没减少。。。。可能是没用邻接表存边的关系吧,参考代码:
#include<iostream>#include<cstring>#include<cstdio>using namespace std;#define MAXN  205#define INS 0xfffffff#define clr(arr) memset(arr,0,sizeof(arr))int map[MAXN][MAXN];int cate[MAXN],index[MAXN],gap[MAXN];int pre[MAXN],q[MAXN],stck[MAXN];bool vis[MAXN],flag;int minres,top;void init_gap_bfs(int n){int v,start,end,size = 100; start = end = 0; index[0] = 1; clr(vis); clr(q);q[start] = n; vis[n] = true; end++;while(start != end){v = q[start]; for(int i = 0;i <= n;++i){if((!vis[i] ) && map[i][v] > 0){vis[i] = true;gap[i] = gap[v] + 1;index[ gap[i] ]++;q[end] = i; end = (end+1)%size;}}start = (start+1)%size;}}bool dfs(int k,int n){int m = minres,minn = INS;for(int i = 0;i <= n;++i){if(gap[k] - gap[i] ==1 && map[k][i] > 0){pre[i] = k; minres = min(minres,map[k][i]);if(i != n)  stck[++top] = i;if(i == n || dfs(i,n)) return true;minres = m;}}index[ gap[k] ]--; index[ gap[k]+1 ]++;    if(index[ gap[k] ] == 0)   flag = true;gap[k] += 1; top--;return false;}int SAP(int b,int n){flag = false; top = 0;int maxflow = 0; stck[top] = b;while(!flag){ clr(pre); pre[0] = -1; minres = INS;    if(top < 0) top = 0;if(!dfs(stck[top],n))   continue;int i = n; maxflow += minres;while(pre[i] != -1){map[ pre[i] ][i] -= minres; map[i][ pre[i] ] += minres;i = pre[i];}top = 0;}   return maxflow;}int main(){//freopen("1.txt","r",stdin);int n,np,nc,m,b,e,v,p;while(~scanf("%d%d%d%d",&n,&np,&nc,&m)){clr(cate); clr(index); clr(gap); clr(stck);memset(map,-1,sizeof(map));for(int i = 0;i < m;++i){scanf(" (%d,%d)%d ",&b,&e,&v);b++; e++;if(map[b][e] == -1) map[b][e] = 0;map[b][e] += v;}for(int i = 0;i < np + nc;++i){scanf(" (%d)%d ",&p,&v);  p++; if(i < np) cate[p] += v;else cate[p] -=v;}for(int i =1;i <= n;++i){if(cate[i] > 0) map[0][i] = cate[i];if(cate[i] < 0) map[i][n+1] = -cate[i];}init_gap_bfs(n+1);printf("%d\n",SAP(0,n+1));}return 0;}