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\)节点,敌人总是选择最优路径即最短路 ...
随机推荐
- Linux mount 命令进阶
笔者在<Linux mount 命令>一文中介绍了 mount 命令的基本用法,本文我们接着介绍 mount 命令的一些高级用法,比如 bind mounts(绑定挂载)和 shared ...
- css3 动画效果实现
前沿 在工作中,经常有一些需要切换的交互样式.如果直接在两种状态之间切换,就显得有点生硬.加上一些动画效果就会好很多. 示例1:点击的三角切换 实现过程 第一步实现这个三角形 用的svg 的多边形画法 ...
- 《linux内核设计与实现》第三章
1.进程 进程就是正在执行的程序代码的实时结果,不仅包含可执行代码,还包括其他资源,比如:打开的文件,挂起的信号,内核内部数据结构,处理器状态,一个或多个具有内存映射的内存地址空间及一个或多个执行线程 ...
- 第三个Sprint冲刺第3天
成员:罗凯旋.罗林杰.吴伟锋.黎文衷 组内各成员加紧完成自己的工作.
- PAT 1016 部分A+B
https://pintia.cn/problem-sets/994805260223102976/problems/994805306310115328 正整数A的“D~A~(为1位整数)部分”定义 ...
- 自己写的browse.bat与perl写的url_handler.pl的比较
以前自己也写过Windows下自动打开多个浏览器测试某个URI,提高浏览器兼容性测试效率. 但是写的browse.bat文件还是最基础简陋的 @echo off if '%1'=='-c' ( sta ...
- charCodeAt与fromCharCode
charCodeAt() 方法可返回指定位置的字符的 Unicode 编码 这个返回值是 0 - 65535 之间的整数. stringObject.charCodeAt(index) /* a-z ...
- [转帖]数据中心网络里的Underlay和Overlay
数据中心网络里的Underlay和Overlay https://blog.csdn.net/zjc801blog/article/details/54289683 2017年01月09日 15:47 ...
- Centos7安装Splash
前言 最近在用Scrapy抓取一个网站数据,其中有个页面需要执行js脚本才能加载,所以需要用到Splash. 官网地址:https://splash.readthedocs.io/en/stable/ ...
- jquery 祖先、子孫、同級
jquery向上遍歷,獲取祖先元素 parent()獲取選中元素的父 parents()獲取選中元素的所有的祖先節點,一直到文檔的根元素<html> parentUntil(“元素1”)獲 ...