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. Spring学习日志之纯Java配置的MVC框架搭建

    依赖引入 <dependencies> <dependency> <groupId>javax.servlet</groupId> <artifa ...

  2. python语法基础笔记

    本篇笔记基于博主自己的的学习,理解,总结所写.很多东西可能存在误解,不能保证百分之百的正确. 1. 数据表达1.1 常量和变量1.2 数据类型1.2.1 基本数据元素1.2.1.1 数字1.2.1.2 ...

  3. SoftwareEngineering Individual Project - Word frequency program

    说实话前面c#实在没怎么学过.这次写起来感觉非常陌生,就连怎么引用名空间都忘记了.在经过恶补后还是慢慢地适应了. 1.项目预计用时: 构建并写出大概的数据结构,程序框架及模块: 30min 实现文件夹 ...

  4. c#词频统计命令行程序

    这里将用c#写一个关于词频统计的命令行程序. 预计时间分配:输入处理3h.词条排序打印2h.测试3h. 实际时间分配:输入处理1h.词条排序打印2h.测试3h.程序改进优化6h. 下面将讲解程序的完成 ...

  5. BugPhobia发布篇章:学霸在线系统测试报告

    0x00 :测试报告版本管理 版本号 具体细节 修订时间 V 1.0 整理第一轮迭代用户管理和登陆注册的功能性验证测试,预计将继续网页对浏览器版本的兼容性测试 2015/11/12 V1.0.1 整理 ...

  6. 2-Twenty Fourth Scrum Meeting-20151230

    前言 因为服务器关闭,我们的开发项目也遭遇停滞一个星期.与网站开发负责人员协商之后,29号开放服务器.我们的项目也能够继续下去.比规定的开发时间(截止为2015/12/29)推迟. 事项安排 1.开发 ...

  7. 实现基于SSH的门票管理系统开发的质量属性

    我要做的是一个基于SSH的门票售卖系统,在系统中常见的质量属性有:可用性.可修改性.性能.安全性.易用性. 可用性方面: 可用性是指系统正常运行时间的比例,是通过两次故障之间的时间长度或在系统崩溃情况 ...

  8. Fake NP CodeForces - 805A (思维)

    Tavak and Seyyed are good friends. Seyyed is very funny and he told Tavak to solve the following pro ...

  9. spring mvc的工作原理

    该文转载自:http://blog.csdn.net/u012191627/article/details/41943393 SpringMVC框架介绍 1) spring MVC属于SpringFr ...

  10. 牛客OI周赛7-提高组

    https://ac.nowcoder.com/acm/contest/371#question A.小睿睿的等式 #include <bits/stdc++.h> using names ...