先跑网络流, 然后在残余网络tarjan缩点.

考虑一条边(u,v):

当且仅当scc[u] != scc[v], (u,v)可能出现在最小割中...然而我并不会证明

当且仅当scc[u] = scc[S] && scc[v] == scc[T], (u, v) 必定出现在最小割中. 这个很好脑补, 假如这条边不是满流, 那么S-T就存在增广路了..

------------------------------------------------------------------------------------

#include<cstdio>
#include<cstring>
#include<stack>
 
using namespace std;
 
const int maxn = 4009;
const int maxm = 60009;
const int INF = 10000000;
 
struct edge {
int to, id, cap;
edge *next, *rev;
} E[maxm << 1], *head[maxn], *pt = E;
 
inline void add(int u, int v, int w, int id) {
pt->to = v; pt->cap = w; pt->id = id;
pt->next = head[u]; head[u] = pt++;
}
inline void addedge(int u, int v, int w, int id) {
add(u, v, w, id); add(v, u, 0, -1);
head[u]->rev = head[v];
head[v]->rev = head[u];
}
 
edge *p[maxn], *cur[maxn];
int h[maxn], cnt[maxn], ans[maxm][2], N, S, T;
stack<int> sta;
int dfn[maxn], low[maxn], scc[maxn], CK = 0, n = 0;
 
void maxFlow() {
memset(h, 0, sizeof h);
memset(cnt, 0, sizeof cnt);
for(int i = 0; i < N; i++) cur[i] = head[i];
cnt[0] = N;
edge* e;
for(int x = S, A = INF; h[S] < N; ) {
   for(e = cur[x]; e; e = e->next)
   if(e->cap && h[e->to] + 1 == h[x]) break;
if(e) {
A = min(A, e->cap);
p[e->to] = cur[x] = e;
x = e->to;
if(x == T) {
for(; x != S; x = p[x]->rev->to) {
p[x]->cap -= A;
p[x]->rev->cap += A;
}
A = INF;
x = S;
}
} else {
if(!--cnt[h[x]]) break;
h[x] = N;
for(e = head[x]; e; e = e->next) if(h[e->to] + 1 < h[x] && e->cap) {
h[x] = h[e->to] + 1;
cur[x] = e;
}
++cnt[h[x]];
if(x != S) x = p[x]->rev->to;
}
}
}
 
void tarjan(int x) {
dfn[x] = low[x] = CK++;
sta.push(x);
for(edge* e = head[x]; e; e = e->next) if(e->cap) {
if(!~dfn[e->to])
   tarjan(e->to), low[x] = min(low[x], low[e->to]);
else if(!~scc[e->to]) 
   low[x] = min(low[x], dfn[e->to]);
}
if(dfn[x] == low[x]) {
int t;
do {
t = sta.top(); sta.pop();
scc[t] = n;
} while(t != x);
n++;
}
}
 
int main() {
int m;
scanf("%d%d%d%d", &N, &m, &S, &T); S--; T--;
for(int i = 0; i < m; i++) {
int u, v, c; scanf("%d%d%d", &u, &v, &c); u--; v--;
addedge(u, v, c, i);
}
maxFlow();
memset(dfn, -1, sizeof dfn);
memset(low, -1, sizeof low);
memset(scc, -1, sizeof scc);
for(int i = 0; i < N; i++) if(!~dfn[i]) tarjan(i);
for(int i = 0; i < N; i++)
   for(edge* e = head[i]; e; e = e->next) if(~e->id && !e->cap) {
    if(scc[i] != scc[e->to]) ans[e->id][0] = 1;
    if(scc[i] == scc[S] && scc[e->to] == scc[T]) ans[e->id][1] = 1;
   }
for(int i = 0; i < m; i++)
   printf("%d %d\n", ans[i][0], ans[i][1]);
return 0;
}

------------------------------------------------------------------------------------

1797: [Ahoi2009]Mincut 最小割

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 1476  Solved: 624
[Submit][Status][Discuss]

Description

A,B两个国家正在交战,其中A国的物资运输网中有N个中转站,M条单向道路。设其中第i (1≤i≤M)条道路连接了vi,ui两个中转站,那么中转站vi可以通过该道路到达ui中转站,如果切断这条道路,需要代价ci。现在B国想找出一个路径切断方案,使中转站s不能到达中转站t,并且切断路径的代价之和最小。 小可可一眼就看出,这是一个求最小割的问题。但爱思考的小可可并不局限于此。现在他对每条单向道路提出两个问题: 问题一:是否存在一个最小代价路径切断方案,其中该道路被切断? 问题二:是否对任何一个最小代价路径切断方案,都有该道路被切断? 现在请你回答这两个问题。

Input

第一行有4个正整数,依次为N,M,s和t。第2行到第(M+1)行每行3个正 整数v,u,c表示v中转站到u中转站之间有单向道路相连,单向道路的起点是v, 终点是u,切断它的代价是c(1≤c≤100000)。 注意:两个中转站之间可能有多条道路直接相连。 同一行相邻两数之间可能有一个或多个空格。

Output

对每条单向边,按输入顺序,依次输出一行,包含两个非0即1的整数,分 别表示对问题一和问题二的回答(其中输出1表示是,输出0表示否)。 同一行相邻两数之间用一个空格隔开,每行开头和末尾没有多余空格。

Sample Input

6 7 1 6
1 2 3
1 3 2
2 4 4
2 5 1
3 5 5
4 6 2
5 6 3

Sample Output

1 0
1 0
0 0
1 0
0 0
1 0
1 0

HINT

设第(i+1)行输入的边为i号边,那么{1,2},{6,7},{2,4,6}是仅有的三个最小代价切割方案。它们的并是{1,2,4,6,7},交是 。 【数据规模和约定】 测试数据规模如下表所示 数据编号 N M 数据编号 N M 1 10 50 6 1000 20000 2 20 200 7 1000 40000 3 200 2000 8 2000 50000 4 200 2000 9 3000 60000 5 1000 20000 10 4000 60000

2015.4.16新加数据一组,可能会卡掉从前可以过的程序。

Source

BZOJ 1797: [Ahoi2009]Mincut 最小割( 网络流 )的更多相关文章

  1. BZOJ 1797: [Ahoi2009]Mincut 最小割

    1797: [Ahoi2009]Mincut 最小割 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2076  Solved: 885[Submit] ...

  2. ●BZOJ 1797 [Ahoi2009]Mincut 最小割

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=1797 题解: 详细的讲解去看http://hzwer.com/3217.html首先跑一个最 ...

  3. bzoj 1797: [Ahoi2009]Mincut 最小割【tarjan+最小割】

    先跑一遍最大流,然后对残量网络(即所有没有满流的边)进行tarjan缩点. 能成为最小割的边一定满流:因为最小割不可能割一半的边: 连接s.t所在联通块的满流边一定在最小割里:如果不割掉这条边的话,就 ...

  4. bzoj 1797: [Ahoi2009]Mincut 最小割 (网络流)

    太神了直接看了hzwer的题解,有个新认识,一条路径上满流的一定是这条路径上所有边的最小值. type arr=record toward,next,cap,from:longint; end; co ...

  5. 1797: [Ahoi2009]Mincut 最小割

    1797: [Ahoi2009]Mincut 最小割 链接 分析: 题意为:问一条边是否可能存在于最小割中,是否一定存在于最小割中. 首先最小割的边一定是满流的边.且这条边点两个端点u.v中,至少一个 ...

  6. 【bzoj1797】[Ahoi2009]Mincut 最小割 网络流最小割+Tarjan

    题目描述 给定一张图,对于每一条边询问:(1)是否存在割断该边的s-t最小割 (2)是否所有s-t最小割都割断该边 输入 第一行有4个正整数,依次为N,M,s和t.第2行到第(M+1)行每行3个正 整 ...

  7. bzoj1797: [Ahoi2009]Mincut 最小割

    最大流+tarjan.然后因为原来那样写如果图不连通的话就会出错,WA了很久. jcvb: 在残余网络上跑tarjan求出所有SCC,记id[u]为点u所在SCC的编号.显然有id[s]!=id[t] ...

  8. bzoj1797: [Ahoi2009]Mincut 最小割(最小割+强联通tarjan)

    1797: [Ahoi2009]Mincut 最小割 题目:传送门 题解: 感觉是一道肥肠好的题目. 第二问其实比第一问简单? 用残余网络跑强联通,流量大于0才访问. 那么如果两个点所属的联通分量分别 ...

  9. BZOJ_1797_[Ahoi2009]Mincut 最小割_最小割+tarjan

    BZOJ_1797_[Ahoi2009]Mincut 最小割_最小割+tarjan Description A,B两个国家正在交战,其中A国的物资运输网中有N个中转站,M条单向道路.设其中第i (1≤ ...

随机推荐

  1. Vijos 1083 小白逛公园(线段树)

    线段树,每个结点维护区间内的最大值M,和sum,最大前缀和lm,最大后缀和rm. 若要求区间为[a,b],则答案max(此区间M,左儿子M,右儿子M,左儿子rm+右儿子lm). ----------- ...

  2. js表格排序 & 去除字符串空格

    // a:列数 bool:排序升序判断参数 true false Str:支持多列 function newUnitSort(a, bool, str) { var oTable = document ...

  3. virtualbox 中安装win7虚拟机

    下载了win7镜像文件后,在virtualbox中装了几次都提示 windows faied to start,后来在网上找了些解决办法,在这记录下,免得下次又忘了 创建新的虚拟机: 1.安装virt ...

  4. [LeetCode]题解(python):001-Two-Sum

    题目来源: https://leetcode.com/problems/two-sum/ 题意分析: 这道题目是输入一个数组和target,要在一个数组中找到两个数字,其和为target,从小到大输出 ...

  5. java时间验证工具

    可以验证2014-02-21这种错误

  6. KISSY对vm的抽取

    vm <script type="text/javascript"> KISSY.use(['bops/js/forced-closure', 'common/js/t ...

  7. COB封装的优势

    随着固态照明技术的不断进步,COB(chip-on-board)封装技术得到越来越多的重视,由于COB光源有热阻低,光通量密度高,眩光少,发光均匀等特性,在室内外照明灯具中得到了广泛的应用,如筒灯,球 ...

  8. Mark Russinovich 的博客:Windows Azure 主机更新:原因、时间和方式

     Mark Russinovich的技术博客涵盖 Windows故障排除.技术和安全等主题. Windows Azure主机更新:原因.时间和方式 Windows Azure的计算平台(其中包括 ...

  9. kinect for windows - DepthBasics-D2D详解之三

    这篇文章我们将总结一下,之前两篇文章中提到的Kinect SDK的函数接. 函数接口: NuiGetSensorCount: 获取连接的Kinect设备个数 原型:_Check_return_ HRE ...

  10. HDU 1348 Wall

    题解:计算凸包周长 #include <iostream> #include <cmath> #include <algorithm> const int size ...