ACM学习-破坏行动-最大网络流

来源:互联网 发布:亚马逊和淘宝哪个大 编辑:程序博客网 时间:2024/04/25 15:52
// ACM学习-破坏行动-最大网络流.cpp : 定义控制台应用程序的入口点。
//
#define _CRT_SECURE_NO_WARNINGS 
#include "stdafx.h"
#include<string>
#include<stdlib.h>
#include<time.h>
#include<iostream>


using namespace std;


long n, m, s, t;//记录节点数,管道数,A地和B地编号
short g[130][130] = {0}, t1[8500], p, q, queue[130], v[130], pre[130];
long min(long a,long b){
return a < b ? a : b;
}
void augment(long v){
long i = t, j = pre[t];
while (i != s){
g[i][j] += v;//增加终端指向源端的流量
g[j][i] -= v;//减少源端到终端的流量
i = j, j = pre[i];
}
}
void maxflow(){
long i, j;
while (1){
memset(pre,0xff,sizeof(pre));
for (int i = 0; i < n; i++)v[i] = 30000;
p = q = 0;//p是队头指针,q是队尾指针
queue[0] = s;//把源点加入到队列中
for (; p <= q; p++){
i = queue[p];
for (j = 0; j < n; j++)
if (g[i][j]>0 && pre[j] < 0){//i--j这条路还可以增加流量
//j点没有被访问过
pre[j] = i;
v[j] = min(v[i],g[i][j]);
queue[++q] = j;
}


if (pre[t]>0) break;//如果找到一条到达汇点的增广路退出循环
}//外for
if (pre[t] >= 0){
augment(v[t]);
}
else{
break;
}
}
}
void solve(){
long i, j, k, tot;
for ( i = 0; i < n; i++){//i为中间点
for ( j = 0; j < n;j++)
for (k = 0; k < n; k++)
{
if (g[j][i] && g[i][k])g[j][k] = 1;
}
 
}
tot = 0;
//统计所有流量为0的残量边总数,即为所求
for (k = 0; k < m; k++){
i = t1[k] / n;
j = t1[k] % n;
if (g[i][j] == 0 || g[j][i] == 0)
{
tot++;
printf("%d\n", k+1);

}
}
printf("%d\n",tot);

}
int _tmain(int argc, _TCHAR* argv[])
{
//freopen("destroy.in","r",stdin);
//freopen("destroy.out","w",stdout);
long i, j, k, c;
scanf_s("%d%d%d%d",&n,&m,&s,&t);
s--, t--;//节点从零开始编号
for (k = 0; k < m; k++){
scanf_s("%d%d%d",&i,&j,&c);
i--;
j--;
g[i][j] = g[j][i] = c;
t1[k] = i*n + j;
}
maxflow();
solve();
return 0;
}

0 0
原创粉丝点击