题目

题意:

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

分割-----------------------------------------

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

输入:

输入文件包含几组输入。每一组的描述如下。每个集合的第一行有两个整数,用空格隔开:第一个是网络中的城市数量n,最多为50。第二个是连接的总数,m,最多500。以下m行指定连接。每条线由三部分组成,中间用空格隔开:前两部分是由这两部分连接起来的城市(数字在1 - n范围内)。然后是切断连接的成本(范围为1到40000000的整数)。在这个列表中,每对引用最多只能出现一次。当n和m的值为0时,输入终止。这种情况不应该处理。对于每个输入集,首都是第1个城市,最大的城市是第2个城市。

输出:

对于每个输入集,您应该生成几行输出。每个输入集的输出描述如下:每个输入集的输出应该是城市对(即数字),它们之间的连接应该被切断(以任何顺序),每对在一行,数字之间用空格隔开。如果有多个解决方案,任何一个都可以。在每个输入集的输出之后打印空行。

题解:

 1 void addedge(int u, int v, int w)  //建双向边
2 { //u为起点,v为终点,w为边上的流量
3 edge[tot].v = v;
4 edge[tot].w = w;
5 edge[tot].next = head[u];
6 head[u] = tot++;
7
8 edge[tot].v = u;
9 edge[tot].w = w;
10 edge[tot].next = head[v];
11 head[v] = tot++;
12 return;
13 }

我之前就有一个疑问就是,为什么在建有向边的时候还要建一条容量为0的反向边。

其实这就是为了反悔之前的操作,因为我们第一次跑最大流的时候肯定会有好多路都可以跑到终点。但是我们最后要的是最大流,这就要考虑到最优策略,所以我们之前走过的路可能要改变。这个时候建立反向边的作用就体现了

代码:

//本题是可以双向走,那么我们正向也可以反向也可以,所以我们在建反向边的时候就不能给它初始值为0,因为
//他刚开始反向边就可以走 //在最后一次bfs之后,肯定就会出现断层(即,到不了终点),这个时候因为中间出现了流量为0所以到不了,
//那么这些流量为0就是我们删去的边
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
const int maxn=10005;
const int INF=0x3f3f3f3f;
int head[maxn],cnt,st,en,dis[maxn],cur[maxn],xx[maxn],yy[maxn];
struct edge
{
int v,next,c,flow;
} e[100005];
void add_edge(int x,int y,int z)
{
e[cnt].v=y;
e[cnt].c=z;
e[cnt].flow=0;
e[cnt].next=head[x];
head[x]=cnt++;
}
bool bfs()
{
memset(dis,0,sizeof(dis));
dis[st]=1;
queue<int>r;
r.push(st);
while(!r.empty())
{
int x=r.front();
r.pop();
for(int i=head[x];i!=-1;i=e[i].next)
{
int v=e[i].v;
if(!dis[v] && e[i].c>e[i].flow)
{
dis[v]=dis[x]+1;
r.push(v);
}
}
}
return dis[en];
}
int dinic(int s,int limit)
{
if(s==en || !limit) return limit;
int ans=0;
for(int &i=cur[s];i!=-1;i=e[i].next)
{
int v=e[i].v,feed;
if(dis[v]!=dis[s]+1) continue;
feed=dinic(v,min(limit,e[i].c-e[i].flow));
if(feed)
{
e[i].flow+=feed;
e[i^1].flow-=feed;
limit-=feed;
ans+=feed;
if(limit==0) break;
}
}
if(!ans) dis[s]=-1;
return ans;
}
int main()
{
int s,d,n,m;
while(~scanf("%d%d",&n,&m) && n+m)
{
memset(head,-1,sizeof(head));
cnt=0;
st=1;
en=2;
int x,y,z;
for(int i=1;i<=m;++i)
{
scanf("%d%d%d",&x,&y,&z);
xx[i]=x;
yy[i]=y;
add_edge(x,y,z);
add_edge(y,x,z);
} int ans=0;
while(bfs())
{
for(int i=0; i<=n; i++)
cur[i]=head[i];
ans+=dinic(st,INF);
}
for(int i=1;i<=m;++i)
{
if((!dis[xx[i]] && dis[yy[i]]) || (dis[xx[i]] && !dis[yy[i]]))
{
printf("%d %d\n",xx[i],yy[i]);
}
}
printf("\n");
}
return 0;
}

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

  1. Uva 10480 Sabotage 最大流

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

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

    UVA 10480 Sabotage (网络流,最大流,最小割) Description The regime of a small but wealthy dictatorship has been ...

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

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

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

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

  5. J - Sabotage - UVA 10480(最大流)

    题目大意:旧政府有一个很庞大的网络系统,可以很方便的指挥他的城市,起义军为了减少伤亡所以决定破坏他们的网络,使他们的首都(1号城市)和最大的城市(2号城市)不能联系,不过破坏不同的网络所花费的代价是不 ...

  6. UVA - 10480 Sabotage (Dinic)

    The regime of a small but wealthy dictatorship has been abruptly overthrown by an unexpected rebel-l ...

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

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

  8. UVA 10480 Sabotage

    最小割+输出方案 #include<cstdio> #include<cstring> #include<string> #include<cmath> ...

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

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

随机推荐

  1. Selenium WebDriver 8大定位方式

    Selenium WebDriver 8大定位方式: driver.find_element_by_id() driver.find_element_by_name() driver.find_ele ...

  2. Openstack Ocata 公共服务端(三)

    Openstack Ocata 公共服务端 mysql 安装: yum install mariadb mariadb-server mysql 安装过程省略 rabbit-server 安装包: # ...

  3. linux线程数限制与zabbix监控

    Linux最大线程数限制及当前线程数查询 最大线程数计算方式: n = total_memory/128k; Linux用户线程数限制而导致的程序异常为 java.lang.OutOfMemoryEr ...

  4. 使用line_profiler对python代码性能进行评估优化

    性能测试的意义 在做完一个python项目之后,我们经常要考虑对软件的性能进行优化.那么我们需要一个软件优化的思路,首先我们需要明确软件本身代码以及函数的瓶颈,最理想的情况就是有这样一个工具,能够将一 ...

  5. HTML基础复习4

    CSS的应用 模块的边框 设置边框样式 border-style::如果是一个值那么表示四个边的样式都一样:如果是两个值那么第一个值代表上下,第二个值代表左右:如果是三个值,第一个值代表上,第二个值代 ...

  6. Gradle使用及配置

    构建工具:Gradle(6.8) 下载地址:https://gradle.org/releases/ 下载最新版的二进制文件即可,下载"gradle-6.8.1-bin.zip文件,下载后完 ...

  7. (01)-Python3之--字符串操作

    1.字符串切片取值 字符串的取值通过索引来读取,从0开始. 取区间值如下:字符串变量名[起始索引:结束索引].包含起始,但不包含结束.例如: str_my = "hello,python!我 ...

  8. VirtualBox Guest Additions 下载地址以及简介

    下载者可将以下链接粘贴到浏览器上,根据Vbox的版本找到自己对应的增强. http://download.virtualbox.org/virtualbox/5.0.10/ 虚拟机安装VBoxAddi ...

  9. 显示HDFS中指定的文件读写权限、大小、创建时间、路径等信息。

    1 import org.apache.hadoop.fs.*; 2 import java.text.SimpleDateFormat; 3 public class D_ReadFileStatu ...

  10. c++11之override关键字

    明确是用来 覆盖 用来对虚函数的  从新实现  加上后编译器就会帮我们去检查这个语法 总结就是:c++11允许派生类显示的注明它将使用那个成员函数改写基类的虚函数 https://blog.csdn. ...