UVA 10480 Sabotage (网络流,最大流,最小割)

Description

The regime of a small but wealthy dictatorship has been abruptly overthrown by an unexpected rebel-lion. Because of the enormous disturbances this is causing in world economy, an imperialist military super power has decided to invade the country and reinstall the old regime.

For this operation to be successful, communication between the capital and the largest city must be completely cut. This is a difficult task, since all cities in the country are connected by a computer network using the Internet Protocol, which allows messages to take any path through the network.

Because of this, the network must be completely split in two parts, with the capital in one part and the largest city in the other, and with no connections between the parts.

There are large differences in the costs of sabotaging different connections, since some are much more easy to get to than others.

Write a program that, given a network speci cation and the costs of sabotaging each connection, determines which connections to cut in order to separate the capital and the largest city to the lowest possible cost

Input

Input file contains several sets of input. The description of each set is given below.

The first line of each set has two integers, separated by a space: First one the number of cities,n in the network, which is at most 50. The second one is the total number of connections, m , at most 500.

The following m lines specify the connections. Each line has three parts separated by spaces: The first two are the cities tied together by that connection (numbers in the range 1-n.Then follows the cost of cutting the connection (an integer in the range 1 to 40000000). Each pair of cites can appear at most once in this list

Input is terminated by a case where values of n and m are zero. This case should not be processed. For every input set the capital is city number 1, and the largest city is number 2.

Output

For each set of input you should produce several lines of output. The description of output for each set of input is given below:

The output for each set should be the pairs of cities (i.e. numbers) between which the connection should be cut (in any order), each pair on one line with the numbers separated by a space. If there is more than one solution, any one of them will do.

Print a blank line after the output for each set of input

Sample Input

5 8

1 4 30

1 3 70

5 3 20

4 3 5

4 5 15

5 2 10

3 2 25

2 4 50

5 8

1 4 30

1 3 70

5 3 20

4 3 5

4 5 15

5 2 10

3 2 25

2 4 50

0 0

Sample Output

4 1

3 4

3 5

3 2

4 1

3 4

3 5

3 2

Http

https://vjudge.net/problem/UVA-10480

Source

网络流,最大流,最小割

题目大意

在给定的无向图中,割去权值和最小的边使得1和2不连通

解决思路

根据最小割最大流定理,最大流即为最小割。所以本题的最小割是可以很快求出来的,关键是如何输出割去哪些边。

因为在执行完最大流算法后,剩下的残量网络图是把S和T割开的,图中的点组成S和T两个集合,所以可以用一遍dfs求出与S在同一边的点,然后从这些点出发,寻找与其相连的不与S相连的点,即跨越了集合S和集合T的边,这些边就是要割掉的。

这里使用Dinic算法实现最大流,可以参考这篇文章

代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std; const int maxN=60;
const int maxM=2000;
const int inf=2147483647; class Edge
{
public:
int u,v,flow;
bool edge;
}; int n,m;
int cnt;
int Head[maxN];
int Next[maxM];
Edge E[maxM];
int depth[maxN];
int cur[maxN];
int Q[maxM];
bool is_outp[maxN][maxN];
bool setS[maxN]; void Add_Edge(int u,int v,int flow);
bool bfs();
int dfs(int u,int flow);
void outp(int u); int main()
{
bool op=0;//用来标记是否是第一组数据,因为要在每两组数据之间输出一个空行
while (cin>>n>>m)
{
if ((n==0)&&(m==0))
break;
if (op)
printf("\n");
op=1;
cnt=-1;//初始化为-1
memset(Head,-1,sizeof(Head));
for (int i=1;i<=m;i++)
{
int u,w,v;
scanf("%d%d%d",&u,&v,&w);//连边
Add_Edge(u,v,w);
Add_Edge(v,u,w);
}
while (bfs())//求解最大流
{
for (int i=1;i<=n;i++)
cur[i]=Head[i];
while (dfs(1,inf));
}
memset(is_outp,0,sizeof(is_outp));//标记某对点是否已经输出
memset(setS,0,sizeof(setS));//标记某个点是否在集合S中
outp(1);//dfs求在集合S中的点
for (int i=1;i<=n;i++)
if (setS[i]==1)
{
for (int j=Head[i];j!=-1;j=Next[j])//寻找横跨两个集合的边
{
int v=E[j].v;
if ((setS[v]==0)&&(is_outp[i][v]==0))//注意判重
{
printf("%d %d\n",i,v);
is_outp[i][v]=1;
}
}
}
/*
for (int i=0;i<=cnt;i++)
if ((E[i].flow==0)&&(E[i].edge==1))
printf("%d %d\n",E[i].u,E[i].v);
//*/
}
} void Add_Edge(int u,int v,int flow)
{
cnt++;
Next[cnt]=Head[u];
Head[u]=cnt;
E[cnt].u=u;
E[cnt].v=v;
E[cnt].flow=flow;
E[cnt].edge=1; cnt++;
Next[cnt]=Head[v];
Head[v]=cnt;
E[cnt].v=u;
E[cnt].u=v;
E[cnt].flow=0;
E[cnt].edge=0;
} bool bfs()
{
memset(depth,-1,sizeof(depth));
int h=1,t=0;
Q[1]=1;
depth[1]=1;
do
{
t++;
int u=Q[t];
for (int i=Head[u];i!=-1;i=Next[i])
{
int v=E[i].v;
if ((depth[v]==-1)&&(E[i].flow>0))
{
depth[v]=depth[u]+1;
h++;
Q[h]=v;
}
}
}
while (h!=t);
if (depth[2]==-1)
return 0;
/*for (int i=1;i<=n;i++)
cout<<depth[i]<<" ";
cout<<endl;
getchar();*/
return 1;
} int dfs(int u,int flow)
{
//cout<<u<<endl;
if (u==2)
return flow;
for (int &i=cur[u];i!=-1;i=Next[i])
{
int v=E[i].v;
if ((depth[v]==depth[u]+1)&&(E[i].flow>0))
{
//cout<<i<<" "<<u<<' '<<v<<endl;
//cout<<"E:"<<E[i].u<<" "<<E[i].v<<" "<<E[i].flow<<endl;
//getchar();
int di=dfs(v,min(flow,E[i].flow));
if (di>0)
{
E[i].flow-=di;
E[i^1].flow+=di;
return di;
}
}
}
return 0;
} void outp(int u)
{
setS[u]=1;
for (int i=Head[u];i!=-1;i=Next[i])
if ((setS[E[i].v]==0)&&(E[i].flow>0))//注意要流量大于0
outp(E[i].v);
return;
}

UVA 10480 Sabotage (网络流,最大流,最小割)的更多相关文章

  1. 网络流 最大流—最小割 之SAP算法 详解

    首先引入几个新名词: 1.距离标号: 所谓距离标号 ,就是某个点到汇点的最少的弧的数量(即边权值为1时某个点到汇点的最短路径长度). 设点i的标号为level[i],那么如果将满足level[i]=l ...

  2. UVA - 10480 Sabotage【最小割最大流定理】

    题意: 把一个图分成两部分,要把点1和点2分开.隔断每条边都有一个花费,求最小花费的情况下,应该切断那些边.这题很明显是最小割,也就是最大流.把1当成源点,2当成汇点,问题是要求最小割应该隔断那条边. ...

  3. UVA - 10480 Sabotage 最小割,输出割法

    UVA - 10480 Sabotage 题意:现在有n个城市,m条路,现在要把整个图分成2部分,编号1,2的城市分成在一部分中,拆开每条路都需要花费,现在问达成目标的花费最少要隔开那几条路. 题解: ...

  4. 最大流-最小割 MAXFLOW-MINCUT ISAP

    简单的叙述就不必了. 对于一个图,我们要找最大流,对于基于增广路径的算法,首先必须要建立反向边. 反向边的正确性: 我努力查找了许多资料,都没有找到理论上关于反向边正确性的证明. 但事实上,我们不难理 ...

  5. UVA 10480 Sabotage (最大流) 最小割边

    题目 题意: 编写一个程序,给定一个网络规范和破坏每个连接的成本,确定要切断哪个连接,以便将首都和最大的城市分离到尽可能低的成本. 分割-------------------------------- ...

  6. Uva 10480 Sabotage 最大流

    表示自从学了网络流,就基本上是一直用dinic 这个题一看就是用最大流,作为常识,两个点之间的最大流等于最小割 但是这个题需要输出割边,然后我就不会了,dinic判流量我觉得也可做,但是一直wa 然后 ...

  7. 「网络流24题」「LuoguP2774」方格取数问题(最大流 最小割

    Description 在一个有 m*n 个方格的棋盘中,每个方格中有一个正整数.现要从方格中取数,使任意 2 个数所在方格没有公共边,且取出的数的总和最大.试设计一个满足要求的取数算法.对于给定的方 ...

  8. UVA 10480 Sabotage (最大流最小割)

    题目链接:点击打开链接 题意:把一个图分成两部分,要把点1和点2分开.隔断每条边都有一个花费,求最小花费的情况下,应该切断那些边. 这题很明显是最小割,也就是最大流.把1当成源点,2当成汇点. 问题是 ...

  9. 最大流&最小割 - 专题练习

    [例1][hdu5889] - 算法结合(BFS+Dinic) 题意 \(N\)个点\(M\)条路径,每条路径长度为\(1\),敌人从\(M\)节点点要进攻\(1\)节点,敌人总是选择最优路径即最短路 ...

随机推荐

  1. 通过容器提交镜像(docker commit)以及推送镜像(docker push)笔记

    在本地创建一个容器后,可以依据这个容器创建本地镜像,并可把这个镜像推送到Docker hub中,以便在网络上下载使用. 查看镜像 [root@docker-test1 ~]# docker image ...

  2. Centos下DNS+NamedManager高可用部署方案完整记录

    之前说到了NamedManager单机版的配置,下面说下DNS+NamedManager双机高可用的配置方案: 1)机器环境 主机名 ip地址 dns01.kevin.cn 192.168.10.20 ...

  3. linux系统最小化安装后的初始化脚本

    作为运维人员,经常会初始化系统,系统在安装过程中基本都会选择最小化安装,这样安装好的系统里会缺少很多环境. 下面分享一个系统安装后的初始化脚本: #!/bin/bash #系统时最小化安装的,这里要安 ...

  4. Java开发23种设计模式之禅

    六大原则 23种设计模式: 总体来说设计模式分为三大类: *创建型模式,共五种:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式. *结构型模式,共七种:适配器模式.装饰器模式.代理模式.外 ...

  5. 关于dreamweaver的软件测评

    最近在用javascript编写程序,于是便用到了dreamweaver .所以,想写一个关于dreamweaver的软件测评. 学生本人使用的是dreamweaver 8.首先,谈谈本人使用感受,打 ...

  6. M1阶段个人总结

    经过4周的开发,我们团队的第一阶段已经结束了. 这一个月来我由于其他事情较多,所以开发的工作主要交给了另外的三名同学. 我主要负责制定代码规范和工程结构,通过github来跟进项目进度,提供一些技术支 ...

  7. Linux内核分析作业第八周

    进程的切换和系统的一般执行过程 一.进程调度的时机 中断处理过程(包括时钟中断.I/O中断.系统调用和异常)中,直接调用schedule(),或者返回用户态时根据need_resched标记调用sch ...

  8. 第三个Sprint ------第九天

    四则运算APP内侧: 1将APP安装包apk发到QQ群(班群),让自己班的同学率先体检.通过同学们的反馈.及时处理好bug,快速迭代. 2将APP下载链接发到微信朋友圈,QQ空间,让其他学校的同学也体 ...

  9. MyEclipse项目里面出现红叉的解决方案?

    一般出现在从别处import的项目上,只有项目文件夹上有红叉,其他地方都正常,现总结个人的几个解决方案:   有几种可能: 1,编码设置是否一致,也即是你项目原来的编码和现在eclipse用的默认编码 ...

  10. redis演练

    如何查看所有的key:keys * 如何查询某个key的value:get keyname