网络流关键路径

本文探讨了如何在网络流问题中找到关键路径。通过计算石油管道网的最大流,然后在残留网络上应用Floyd算法判断哪些管道的减少容量会影响整体网络流。这种方法避免了逐一检查饱和边并重新计算网络流的低效过程。程序实现包括最大流算法和Floyd算法来确定关键路径。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

/*

输入一个石油管道网,管道可以双向流通石油,即可以使用网络流计算最大流

输出网络最大流的关键路径,即降低某一管道的容量会使整个网络流降低。

首先可以尝试的方式是先计算最大流,然后遍历所有容量饱和的边,降低这些边的容量重新计算网络流和原网络流比较,太慢。

可以假象当前网络流已经达到最大,如果把一个饱和边的容量降低1,那么包和边的起点就会堆积1个流量而饱和边的终点会少了1流量,

如果在残留网络中,从这个起点到终点有一条容量大于等于1的增广路径,就不会影响整个网络流。如果只考虑在饱和边上最多只能降低1个流量

那么在残留网络中起点终点的增广路径就可以看做是起点终点在残留网络中的连通性,这样可以在残留网络上应用floyd求出节点之间的闭包,即连通性。

floyd会把连通饱和边的可用容量设置为1,在floyd应用完毕之后,管道中可用容量仍为0的就是关键路径。

*/

#include<fstream>

#include<iostream>

#define MAXNUM 10

#define MAXQUEUE 100

#define MAXWAY 10

using namespace std;

int G[MAXNUM][MAXNUM];

int n,m,s,t;

int tunnel[MAXWAY];

ifstream fin("input.txt");

void maxflow(){

int head,tail;

int i,j;

int v[MAXQUEUE];

int pre[MAXNUM];

int minflow[MAXNUM];

while(1){

memset(pre,0,sizeof(pre));

for(i=0;i<MAXNUM;i++)

minflow[i] = 9999;

head=0;

tail=0;

v[tail++] = s;

while(1){//寻找增广路

i = v[head++];

for(j=1;j<=n;j++){

if(G[i][j]&&!pre[j]){

pre[j] = i;

v[tail++] = j;

minflow[j] = min(minflow[i],G[i][j]);

//minflow = min(minflow,G[i][j]);不可以这样写,这样会把非路径上的路也算上

}

}

if(pre[t])

break;

if(head == tail)

break;

}

if(pre[t]){//扩增路径

i=pre[t];

j=t;

while(1){

cout<< i << " -> " << j << minflow[t] << endl;

G[i][j] -= minflow[t];

G[j][i] += minflow[t];

j=i;

i=pre[i];

if(j==s)

break;

}

}else

break;

cout << endl;

}

}

void solve(){//在残余网络上使用floyd求闭包

int i,j,k;

int cnt=0;

for(k=1;k<=n;k++){

for(i=1;i<=n;i++)

for(j=1;j<=n;j++)

if(G[i][k]&&G[k][j])

G[i][j] = 1;

}

 

 

for(i=0;i<m;i++){

j = tunnel[i]/(n+1);

k = tunnel[i]%(n+1);

if(!G[j][k]||!G[k][j]){

cnt++;

cout << j << " -> " << k << endl;

}

}

//cout << cnt;

}

int main(){

fin >> n >> m >> s >> t;

int i,x,y,g;

memset(G,0,sizeof(G));

for(i=0;i<m;i++){

fin >> x >> y >> g;

G[x][y] = g;

G[y][x] = g;

tunnel[i] = x*(n+1) + y; 

}

maxflow();

solve();

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值