UVA 10480 Sabotage (网络流,最大流,最小割)
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 (网络流,最大流,最小割)的更多相关文章
- 网络流 最大流—最小割 之SAP算法 详解
首先引入几个新名词: 1.距离标号: 所谓距离标号 ,就是某个点到汇点的最少的弧的数量(即边权值为1时某个点到汇点的最短路径长度). 设点i的标号为level[i],那么如果将满足level[i]=l ...
- UVA - 10480 Sabotage【最小割最大流定理】
题意: 把一个图分成两部分,要把点1和点2分开.隔断每条边都有一个花费,求最小花费的情况下,应该切断那些边.这题很明显是最小割,也就是最大流.把1当成源点,2当成汇点,问题是要求最小割应该隔断那条边. ...
- UVA - 10480 Sabotage 最小割,输出割法
UVA - 10480 Sabotage 题意:现在有n个城市,m条路,现在要把整个图分成2部分,编号1,2的城市分成在一部分中,拆开每条路都需要花费,现在问达成目标的花费最少要隔开那几条路. 题解: ...
- 最大流-最小割 MAXFLOW-MINCUT ISAP
简单的叙述就不必了. 对于一个图,我们要找最大流,对于基于增广路径的算法,首先必须要建立反向边. 反向边的正确性: 我努力查找了许多资料,都没有找到理论上关于反向边正确性的证明. 但事实上,我们不难理 ...
- UVA 10480 Sabotage (最大流) 最小割边
题目 题意: 编写一个程序,给定一个网络规范和破坏每个连接的成本,确定要切断哪个连接,以便将首都和最大的城市分离到尽可能低的成本. 分割-------------------------------- ...
- Uva 10480 Sabotage 最大流
表示自从学了网络流,就基本上是一直用dinic 这个题一看就是用最大流,作为常识,两个点之间的最大流等于最小割 但是这个题需要输出割边,然后我就不会了,dinic判流量我觉得也可做,但是一直wa 然后 ...
- 「网络流24题」「LuoguP2774」方格取数问题(最大流 最小割
Description 在一个有 m*n 个方格的棋盘中,每个方格中有一个正整数.现要从方格中取数,使任意 2 个数所在方格没有公共边,且取出的数的总和最大.试设计一个满足要求的取数算法.对于给定的方 ...
- UVA 10480 Sabotage (最大流最小割)
题目链接:点击打开链接 题意:把一个图分成两部分,要把点1和点2分开.隔断每条边都有一个花费,求最小花费的情况下,应该切断那些边. 这题很明显是最小割,也就是最大流.把1当成源点,2当成汇点. 问题是 ...
- 最大流&最小割 - 专题练习
[例1][hdu5889] - 算法结合(BFS+Dinic) 题意 \(N\)个点\(M\)条路径,每条路径长度为\(1\),敌人从\(M\)节点点要进攻\(1\)节点,敌人总是选择最优路径即最短路 ...
随机推荐
- JVM规范系列第2章:Java虚拟机结构
本规范描述的是一种抽象化的虚拟机的行为,而不是任何一种(译者注:包括 Oracle 公司自己的 HotSpot 和 JRockit 虚拟机)被广泛使用的虚拟机实现. 记住:JVM规范是一种高度抽象行为 ...
- J-query extend()方法
1.如果没有冲突参数会弥在后面. 2.参数如果和前面的参数存在相同的名称,那么后面的会覆盖前面的参数值.
- centos6.5虚拟机安装后,没有iptables配置文件
openstack环境里安装centos6.5系统的虚拟机,安装好后,发现没有/etc/syscofig/iptables防火墙配置文件. 解决办法如下: [root@kvm-server005 ~] ...
- linux-镜像下载
https://blog.csdn.net/sinat_36564972/article/details/81560395 Centos6.5镜像下载 2018年08月10日 11:35:53 深夜搬 ...
- #个人博客作业Week1——浏览教材后提出的六个问题及软件与软件工程的提出。
1.通常,我们阅读软件比编写软件花费的时间更多.正因为编写软件比阅读软件要容易,因此代码的可读性显得尤为重要.那么我们在写程序时应该如何避免多余的,带有误导性的注释,写出一个利于帮助别人读懂程序的注释 ...
- 【ML】ICML2015_Unsupervised Learning of Video Representations using LSTMs
Unsupervised Learning of Video Representations using LSTMs Note here: it's a learning notes on new L ...
- Docker中安装Nexus3
https://blog.csdn.net/sqandczm/article/details/78560710 https://hub.docker.com/r/sonatype/nexus/ htt ...
- [转帖]台积电近10万片晶圆报废,但7nm工艺将成2019营收主力
台积电近10万片晶圆报废,但7nm工艺将成2019营收主力 2019年02月18日 13:19 1784 次阅读 稿源:Expreview超能网 0 条评论 https://www.cnbeta.co ...
- FuelPHP 系列(五) ------ Security 防御
项目中难免会有 form 提交,对用户输入的所有信息进行过滤,可以避免 XSS 攻击,防止 SQL 注入. 一.设置配置信息 首先在 config.php 文件中,对 security 相关信息进行设 ...
- React 表单控件onSubmit
<!DOCTYPE html><html><head lang="en"> <meta charset="UTF-8" ...