https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1421

题意:给出n个点m条边,每条边有一个花费,问将1和2隔离需要破坏的边的最小花费的边集。

思路:很明显是最小割,但是问题在于如何求出这个最小割集。通过以前的题目,求网络的最大流就是求网络的最小割,那么从源点到汇点的最大流必定就会经过最小割集的边,当这条边满载(flow == cap)的时候,这条边其实就是最小割集的边。求出最大流之后,整个残余网络会被分成两个集合,一个和源点直接间接相连的点集,另一个和汇点直接间接相连的点集,所以只要BFS从源点或者汇点往前扫,一边扫一边标记,直到扫到(flow == cap)的边就停止。然后枚举边,如果一条边有一边的顶点是被标记过的,另一边的顶点没被标记,那么这条边就是最小割集之一了。

 #include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <string>
#include <iostream>
#include <stack>
#include <map>
#include <queue>
#include <set>
using namespace std;
typedef long long LL;
#define N 55
#define M 505
#define INF 0x3f3f3f3f
struct Edge {
int u, v, cap;
Edge () {}
Edge (int u, int v, int cap) : u(u), v(v), cap(cap) {}
} edge[M*];
vector<int> G[N];
int dis[N], cur[N], S, T, tot, vis[N], mp[N][N]; void Add(int u, int v, int cap) {
edge[tot] = Edge(u, v, cap);
G[u].push_back(tot++);
edge[tot] = Edge(v, u, );
G[v].push_back(tot++);
} int BFS() {
memset(dis, INF, sizeof(dis));
queue<int> que;
que.push(S); dis[S] = ;
while(!que.empty()) {
int u = que.front(); que.pop();
for(int i = ; i < G[u].size(); i++) {
Edge &e = edge[G[u][i]];
if(dis[e.v] == INF && e.cap > ) {
dis[e.v] = dis[u] + ;
que.push(e.v);
}
}
}
return dis[T] < INF;
} int DFS(int u, int maxflow) {
if(u == T) return maxflow;
for(int i = cur[u]; i < G[u].size(); i++) {
cur[u] = i;
Edge &e = edge[G[u][i]];
if(dis[e.v] == dis[u] + && e.cap > ) {
int flow = DFS(e.v, min(e.cap, maxflow));
if(flow > ) {
e.cap -= flow;
edge[G[u][i]^].cap += flow;
return flow;
}
}
}
return ;
} int Dinic() {
int ans = ;
while(BFS()) {
int flow;
memset(cur, , sizeof(cur));
while(flow = DFS(S, INF)) ans += flow;
}
return ans;
} void bfs() {
queue<int> que;
que.push(S); vis[S] = ;
while(!que.empty()) {
int u = que.front(); que.pop();
for(int i = ; i < G[u].size(); i++) {
Edge &e = edge[G[u][i]];
if(!vis[e.v] && e.cap > ) {
vis[e.v] = ;
que.push(e.v);
}
}
}
} int main()
{
int n, m;
while(~scanf("%d%d", &n, &m), n + m) {
int u, v, cap; tot = ;
for(int i = ; i <= n; i++) G[i].clear();
memset(mp, , sizeof(mp));
memset(vis, , sizeof(vis));
for(int i = ; i < m; i++) {
scanf("%d%d%d", &u, &v, &cap);
Add(u, v, cap); Add(v, u, cap);
} S = , T = ;
Dinic();
bfs();
for(int u = ; u <= n; u++) {
for(int i = ; i < G[u].size(); i++) {
int v = edge[G[u][i]].v;
if(vis[u] && !vis[v] || vis[v] && !vis[u]) mp[u][v] = mp[v][u] = ;
}
}
for(int i = ; i <= n; i++) {
for(int j = i + ; j <= n; j++) {
if(mp[i][j]) printf("%d %d\n", i, j);
}
}
puts("");
}
return ;
}

UVa 10480:Sabotage (最小割集)的更多相关文章

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

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

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

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

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

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

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

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

  5. Uva 10480 Sabotage 最大流

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

  6. UVA 10480 Sabotage

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

  7. UVA - 10480 Sabotage (Dinic)

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

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

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

  9. hiho 第116周,最大流最小割定理,求最小割集S,T

    小Hi:在上一周的Hiho一下中我们初步讲解了网络流的概念以及常规解法,小Ho你还记得内容么? 小Ho:我记得!网络流就是给定了一张图G=(V,E),以及源点s和汇点t.每一条边e(u,v)具有容量c ...

随机推荐

  1. XF 表视图添加和删除行

    using System;using Xamarin.Forms;using Xamarin.Forms.Xaml; [assembly: XamlCompilation (XamlCompilati ...

  2. CentOS 7.3最小系统安装KVM

    一.准备工作 安装wget和vim yum install -y wget vim 修改yum源为阿里源 wget -O /etc/yum.repos.d/CentOS-Base.repo http: ...

  3. C# 桌面软件开发-深入学习[2]- AY-C#人爱学不学-aaronyang技术分享

    原文:C# 桌面软件开发-深入学习[2]- AY-C#人爱学不学-aaronyang技术分享 1 : C# Assembly.GetEntryAssembly().GetName().Version. ...

  4. Expression Blend学习5控件

    原文:Expression Blend学习5控件 Expression Blend ButtonStyle- TextButton 本章以TextButton为例,讲解如何最简单,最快速的制作一个专业 ...

  5. WPF 遍历 控件

    比较简单的方式是 在设计一个画面时 先添加一个grid 或其他的布局控件 确保要遍历的控件都在这个Grid中时就可以这么写 foreach (UIElement uie in Grid.Childre ...

  6. Android adb shell 无法启动:insufficient permissions for device

    解决办法1:lsusb查看vendorId号,然后在/etc/udev/rules.d/目录下增加(或修改)51-android.rules文件.增加一条记录:SUBSYSTEM=="usb ...

  7. Win8 Metro(C#)数字图像处理--2.49Zhang二值图像细化算法

    原文:Win8 Metro(C#)数字图像处理--2.49Zhang二值图像细化算法  [函数名称]   二值图像细化算法      WriteableBitmap ThinningProcess ...

  8. Oracle报错:不是单组分组函数

    报错:不是单组分组函数 实例:select sum(HWJZ) ,rq from  JcChargeInfo 原因: 1.如果程序中使用了分组函数,则有两种情况可以使用: 程序中存在group by, ...

  9. 内存页面的各种属性(就是Read, Write, Execute的组合)

    PAGE_NOACCESS 禁止写入执行读取查看进程内存区域能发现,NOACCESS属性的内存页面都是FREE状态的(未提交使用的内存区域),只有内存区域最后的0x7FFE1000-0x7FFF000 ...

  10. Android零基础入门第68节:完善RecyclerView,添加首尾视图

    在之前学习ListView的时候,有学习过如何给ListView添加列表头和列表尾.但是通过近几期的学习,发现RecyclerView是一个比ListView更加强大和灵活的组件,今天一起来学习如何给 ...