POJ 1459--Power Network(三种方法求最大流)
来源:互联网 发布:mastercam9.1三维编程 编辑:程序博客网 时间:2024/05/22 02:18
- 根据题意,新建一个超级节点,所有发电站的流量由此节点发出,新建一个超级汇点,所有节点 使用的流量都流到此节点。 然后采用最大流的各种方法求解。
- 不管用ford——fulkerson方法还是推送重贴标签,首先都不用管自环,显然一个最大流是不会包括自环的,自环只会减少流量。然后反向边也不需要如算法导论中加入另外的点进行处理。为了减少内存,直接用容量的减少代表流量的增加,正向边容量减少多少,正向流 量就增加多少,同时增加相应的反向容量,意思就是说反向的能允许的流量增加,而如果接下来的操作反向容量减少,也就是有反向的流量,也即是正向流量的减少,不管正向反向流量都可增可少,但是注意的是实际上最大流只会有一个方向的流量,但是可以等效为上述操作。直至所有增广路径的残余流量都是0。-------------ford——fulkerson
- push——relabel:此算法较难理解,初始化后若一个点有溢出,并且其所有能流入的点(因为在构图里面允许反向边,所以不用像算法导论里面允许一个反向的流量作为残余边 来减少流量,而本算法在对反向容量增加时可以达到同样的效果。所以只要capacity[u][v]>0就说明还有残余流量)高度均大于等于它,就对此点更新高度。若此点高度等于其能流入的点高度加1,则对此边推入操作。因为在满足溢出,可流入条件下,推入和重贴标签是互斥的,可以优化。
- Dinic: 首先BFS分层,为了构造一个有向无环图,当BFS无法到达汇点时,已达最大流。然后对上图作DFS,类似于二分匹配,当DFS到最后一点,其不能向下迭代但是又不是汇点则将此点标记不再走。当到达汇点回溯时,只回溯到路径最小边(u,v),因为显然从u点还可能向下找增广路径,可继续使用u点以前多余的流量,所以要对每点设置一个总增广值sumAug,记录此点能到达的所有增广路径使用的流量,然后再从此点回溯。
ford-fulkerson:
#include<iostream>#include<cstdio>#include<queue>#include<cstring>using namespace std;#define min(x,y) (x>y?y:x)#define INF (0X7F7F)#define maxN 105short capacity[maxN][maxN];short nodeNum;short start;short dest;int maxFlow(){ short fa[maxN]; short minPathFlow[maxN]; queue<short> q; short now,i,tmpFlow,son; int maxFlow = 0; while(1) { memset(fa,127,sizeof(short)*(nodeNum+2)); memset(minPathFlow,127,sizeof(short)*(nodeNum+2)); q.push(start); while(!q.empty()) //寻找始终点最短路径 { now = q.front(); q.pop(); for(i = 0;i <= nodeNum;i++) { tmpFlow = capacity[now][i]; if(fa[i] == INF&&tmpFlow > 0) { if(i == dest) { minPathFlow[dest] = min(minPathFlow[now],tmpFlow); fa[dest] = now; //并查集 break; } else { fa[i] = now; minPathFlow[i] = min(minPathFlow[now],tmpFlow); q.push(i); } } } } if(minPathFlow[dest] != INF) //更新流量 { maxFlow += minPathFlow[dest]; son = dest; while(son != start) { capacity[fa[son]][son] -= minPathFlow[dest]; capacity[son][fa[son]] += minPathFlow[dest]; son = fa[son]; } } else break; } cout<<maxFlow<<endl; return 0;}int main(){ char tmpCh; short u,v,cmax,powerNum,consumerNum,lineNum; while(scanf("%hd%hd%hd%hd",&nodeNum,&powerNum,&consumerNum,&lineNum)!=EOF) { memset(capacity,0,sizeof(short)*(maxN*maxN)); while(lineNum--) { cin>>tmpCh>>u>>tmpCh>>v>>tmpCh>>cmax; capacity[u][v] = cmax; } start = nodeNum+1; dest = nodeNum; while(powerNum--) { cin>>tmpCh>>u>>tmpCh>>cmax; capacity[start][u] = cmax; } while(consumerNum--) { cin>>tmpCh>>u>>tmpCh>>cmax; capacity[u][dest] = cmax; } maxFlow(); } return 0;}
#include<iostream>#include<cstdio>#include<cstring>using namespace std;#define maxN 105#define min(x,y) (x>y?y:x)#define INF (0x7F7F)int capacity[maxN][maxN];short nodeNum;short start,dest;short height[maxN];int exceFlow[maxN];struct node{ short x; node *next; node *prev;}*head;bool push(short u,short v){ int minFlow = min(exceFlow[u],capacity[u][v]); capacity[u][v] -= minFlow; capacity[v][u] += minFlow; exceFlow[u] -= minFlow; exceFlow[v] += minFlow; return true;}bool relabel(short u){ short i; short minHeight = INF; for(i = 0;i < nodeNum;i++) { if(capacity[u][i] > 0&&height[u] <= height[i]) minHeight = min(minHeight,height[i]); } height[u] = minHeight+1; return true;}int discharge(short u){ short v = 0; while(exceFlow[u] > 0) { if(v == nodeNum) { relabel(u); v = 0; } else if(capacity[u][v] > 0&&height[u] == height[v]+1) { push(u,v); } else { v++; } } return 1;}int moveToHead(node *tmp){ if(tmp->prev != NULL) { if(tmp->next != NULL) { tmp->prev->next = tmp->next; tmp->next->prev = tmp->prev; } else { tmp->prev->next = NULL; } tmp->next = head; head->prev = tmp; head = tmp; head->prev = NULL; } return 1;}int relabelToFront(){ short i,u; bool IsMax = false; short oldHeight; bool IsRelabel; /*****Initialize preflow******/ memset(height,0,sizeof(short)*(nodeNum)); height[start] = nodeNum; memset(exceFlow,0,sizeof(int)*(nodeNum)); for(i = 0;i < nodeNum-2;i++) { if(capacity[start][i] > 0) { exceFlow[i] = capacity[start][i]; exceFlow[start] -= capacity[start][i]; capacity[i][start] = capacity[start][i]; capacity[start][i] = 0; } } /*****Init List*********/ node *tmp; head = NULL; for(i = 0;i < nodeNum-2;i++) { tmp = new node; tmp->x = i; tmp->next = head; if(head != NULL) head->prev = tmp; head = tmp; head->prev = NULL; } tmp = head; while(tmp != NULL) { u = tmp->x; oldHeight = height[u]; discharge(u); if(height[u] > oldHeight) { moveToHead(tmp); } tmp = tmp->next; } delete[] tmp; delete[] head; cout<<exceFlow[dest]<<endl; return 1;}int main(){ short powerNum,consumerNum,lineNum; int u,v,cmax; char tmpCh; while(cin>>nodeNum>>powerNum>>consumerNum>>lineNum) { memset(capacity,0,sizeof(int)*(maxN*maxN)); while(lineNum--) { cin>>tmpCh>>u>>tmpCh>>v>>tmpCh>>cmax; if(u != v) capacity[u][v] = cmax; } nodeNum += 2; start = nodeNum-1; dest = nodeNum-2; while(powerNum--) { cin>>tmpCh>>u>>tmpCh>>cmax; capacity[start][u] = cmax; } while(consumerNum--) { cin>>tmpCh>>u>>tmpCh>>cmax; capacity[u][dest] = cmax; } relabelToFront(); } return 0;}
Dinic:
#include<iostream>#include<cstdio>#include<cstring>using namespace std;#define maxN 105#define min(x,y) (x>y?y:x)#define INF (0x7F7F)int capacity[maxN][maxN];short nodeNum;short start,dest;short height[maxN];int maxFlow;int Aug(short u,int minFlow){ short i; int tmpFlow,tmpAug; int sumAug = 0; if(u == dest) { maxFlow += minFlow; return minFlow; //返回增广路径中最小容量,能增加的最大流量 } for(i = 1;i < nodeNum;i++) { if(capacity[u][i] > 0&&height[i] == height[u]+1) { tmpFlow = min(minFlow,capacity[u][i]); tmpAug = Aug(i,tmpFlow); sumAug += tmpAug; //从u点出发可能有不同的增广路径,将所有路径的容量保存在sumAug if(tmpAug) { capacity[u][i] -= tmpAug; capacity[i][u] += tmpAug; if(capacity[u][i] != 0) //若流量减为0,即寻找的增广路径的最小容量在此点,则从此点父节点再往下增广,反之直接返回找到路径容量最小点 return sumAug; else { minFlow -= tmpAug; //再往下增广时,能允许的流量减少 } } else { height[i] = INF; //从i点已无增广路径,将此点锁定不被访问 } } } return sumAug;}int BFS(){ short q[maxN]; short now,rear,i; q[now = rear = 0] = start; memset(height,127,sizeof(short)*(nodeNum)); height[start] = 0; while(now <= rear) { for(i = 1;i < nodeNum;i++) { if(capacity[q[now]][i] > 0&&height[i] == INF) { height[i] = height[q[now]]+1; //可流的两点高度相差一,高度相差一不一定可流 q[++rear] = i; if(i == dest) return 1; } } now++; } return 0;}int Dinic(){ maxFlow = 0; while(BFS()) { Aug(start,INF); } cout<<maxFlow<<endl; return 1;}int main(){ short powerNum,consumerNum,lineNum; int u,v,cmax; char tmpCh; while(cin>>nodeNum>>powerNum>>consumerNum>>lineNum) { memset(capacity,0,sizeof(int)*(maxN*maxN)); while(lineNum--) { cin>>tmpCh>>u>>tmpCh>>v>>tmpCh>>cmax; if(u != v) capacity[++u][++v] = cmax; } nodeNum += 2; start = 0; dest = nodeNum-1; while(powerNum--) { cin>>tmpCh>>u>>tmpCh>>cmax; capacity[start][++u] = cmax; } while(consumerNum--) { cin>>tmpCh>>u>>tmpCh>>cmax; capacity[++u][dest] = cmax; } Dinic(); } return 0;}
0 0
- POJ 1459--Power Network(三种方法求最大流)
- (最大流) poj 1459 Power Network
- POJ--1459[Power Network] 网络最大流
- POJ-1459 Power Network【最大流】
- POJ 1459 Power Network 最大流
- poj 1459 Power Network(最大流)
- poj 1459 Power Network(最大流)
- Poj 1459 Power Network 最大流
- poj 1459 Power Network, 最大流,多源多汇
- POJ 1459 Power Network(最大流)
- POJ 1459 :Power Network:最大流算法
- POJ 1459 Power Network (最大流)
- 【最大流】POJ-1459 Power Network
- poj 1459 Power Network (网络最大流)
- poj 1459 Power Network(最大流)
- POJ 1459 Power Network【多源汇点最大流】
- poj 1459 Power Network (最大流)
- POJ 1459 Power Network(最大流)
- 一步一步入门机器学习之四:约束玻尔兹曼机(RBM)
- Http status code : 304
- 数据库筛选用户,然后去掉一部分(列表求差),再随机返回一个用户。sqlalchemy + python集合(set) + random
- Linux字符驱动中动态分配设备号与动态生成设备节点
- Wax框架简明教程(1) 简介
- POJ 1459--Power Network(三种方法求最大流)
- 求n个数(1~n)的质因子
- LayoutInflater的使用
- 9.asm-汇编mov,lea+[]寻址 小结
- Ajax 两点记录
- Farey Sequence+欧拉函数打表+模板题+poj
- Android模拟神器——Genymotion
- HNU 12834 Thread Tree
- POJ - 3522 Slim Span (kruskal+枚举)