题目

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

输入格式

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

输出格式

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

输入样例

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

输出样例

1 0

1 0

0 0

1 0

0 0

1 0

1 0

提示

设第(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新加数据一组,可能会卡掉从前可以过的程序。

题解

先跑最大流求出任意一个最小割

对残量网络缩点

然后对于一条满流的边(u,v)

①Scc[u]!=Scc[v],存在(u,v)被割的方案

②Scc[u]Scc[S]&&Scc[v]Scc[T],(u,v)必定被割

jcvb:

在残余网络上跑tarjan求出所有SCC,记id[u]为点u所在SCC的编号。显然有id[s]!=id[t](否则s到t有通路,能继续增广)。

①对于任意一条满流边(u,v),(u,v)能够出现在某个最小割集中,当且仅当id[u]!=id[v];

②对于任意一条满流边(u,v),(u,v)必定出现在最小割集中,当且仅当id[u]id[s]且id[v]id[t]。



<将每个SCC缩成一个点,得到的新图就只含有满流边了。那么新图的任一s-t割都对应原图的某个最小割,从中任取一个把id[u]和id[v]割开的割即可证明。



<:假设将(u,v)的边权增大,那么残余网络中会出现s->u->v->t的通路,从而能继续增广,于是最大流流量(也就是最小割容量)会增大。这即说明(u,v)是最小割集中必须出现的边。

  1. #include<iostream>
  2. #include<cmath>
  3. #include<cstdio>
  4. #include<cstring>
  5. #include<queue>
  6. #include<algorithm>
  7. #define LL long long int
  8. #define REP(i,n) for (int i = 1; i <= (n); i++)
  9. #define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
  10. #define BUG(s,n) for (int i = 1; i <= (n); i++) cout<<s[i]<<' '; puts("");
  11. using namespace std;
  12. const int maxn = 4005,maxm = 200005,INF = 1000000000;
  13. inline int read(){
  14. int out = 0,flag = 1; char c = getchar();
  15. while (c < 48 || c > 57) {if (c == '-') flag = -1; c = getchar();}
  16. while (c >= 48 && c <= 57) {out = (out << 3) + (out << 1) + c - '0'; c = getchar();}
  17. return out * flag;
  18. }
  19. int h[maxn],ne = 2,n,m,S,T;
  20. struct EDGE{int from,to,nxt,f;}ed[maxm];
  21. inline void build(int u,int v,int w){
  22. ed[ne] = (EDGE){u,v,h[u],w}; h[u] = ne++;
  23. ed[ne] = (EDGE){v,u,h[v],0}; h[v] = ne++;
  24. }
  25. int vis[maxn],d[maxn],cur[maxn];
  26. bool bfs(){
  27. memset(d,0,sizeof(d));
  28. memset(vis,0,sizeof(vis));
  29. queue<int> q;
  30. vis[S] = true; q.push(S); int u;
  31. while (!q.empty()){
  32. u = q.front(); q.pop();
  33. Redge(u) if (ed[k].f && !vis[to = ed[k].to]){
  34. d[to] = d[u] + 1; vis[to] = true; q.push(to);
  35. }
  36. }
  37. return vis[T];
  38. }
  39. int dfs(int u,int minf){
  40. if (u == T || !minf) return minf;
  41. int f,flow = 0,to;
  42. if (cur[u] == -1) cur[u] = h[u];
  43. for (int& k = cur[u]; k; k = ed[k].nxt)
  44. if (d[to = ed[k].to] == d[u] + 1 && (f = dfs(to,min(ed[k].f,minf)))){
  45. ed[k].f -= f; ed[k ^ 1].f += f;
  46. flow += f; minf -= f;
  47. if (!minf) break;
  48. }
  49. return flow;
  50. }
  51. int maxflow(){
  52. int flow = 0;
  53. while (bfs()){
  54. for (int i = 1; i <= n; i++) cur[i] = -1;
  55. flow += dfs(S,INF);
  56. }
  57. return flow;
  58. }
  59. int dfn[maxn],low[maxn],st[maxn],Scc[maxn],top,cnt,scci;
  60. void dfs(int u){
  61. dfn[u] = low[u] = ++cnt;
  62. st[++top] = u;
  63. Redge(u) if (ed[k].f){
  64. if (!dfn[to = ed[k].to]){
  65. dfs(to);
  66. low[u] = min(low[u],low[to]);
  67. }else if (!Scc[to]) low[u] = min(low[u],dfn[to]);
  68. }
  69. if (dfn[u] == low[u]){
  70. scci++;
  71. do{
  72. Scc[st[top]] = scci;
  73. }while (st[top--] != u);
  74. }
  75. }
  76. int ans[2][maxm];
  77. int main(){
  78. n = read(); m = read(); S = read(); T = read(); int a,b,w;
  79. REP(i,m){
  80. a = read(); b = read(); w = read();
  81. build(a,b,w);
  82. }
  83. maxflow();
  84. REP(i,n) if (!dfn[i]) dfs(i);
  85. for (int i = 1; i <= m; i++){
  86. int k = i << 1;
  87. if (!ed[k].f){
  88. if (Scc[ed[k].from] != Scc[ed[k].to]) ans[0][i] = 1;
  89. if (Scc[ed[k].from] == Scc[S] && Scc[ed[k].to] == Scc[T]) ans[1][i] = 1;
  90. }
  91. }
  92. for (int i = 1; i <= m; i++) printf("%d %d\n",ans[0][i],ans[1][i]);
  93. return 0;
  94. }

BZOJ1797 [Ahoi2009]Mincut 最小割 【最小割唯一性判定】的更多相关文章

  1. bzoj1797: [Ahoi2009]Mincut 最小割

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

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

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

  3. bzoj1797: [Ahoi2009]Mincut 最小割(网络流,缩点)

    传送门 首先肯定要跑一个最小割也就是最大流 然后我们把残量网络tarjan,用所有没有满流的边来缩点 一条边如果没有满流,那它就不可能被割了 一条边如果所属的两个强联通分量不同,它就可以被割 一条边如 ...

  4. 【最小割】【Dinic】【强联通分量缩点】bzoj1797 [Ahoi2009]Mincut 最小割

    结论: 满足条件一:当一条边的起点和终点不在 残量网络的 一个强联通分量中.且满流. 满足条件二:当一条边的起点和终点分别在 S 和 T 的强联通分量中.且满流.. 网上题解很多的. #include ...

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

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

  6. 【BZOJ-1797】Mincut 最小割 最大流 + Tarjan + 缩点

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

  7. BZOJ 1797: [Ahoi2009]Mincut 最小割( 网络流 )

    先跑网络流, 然后在残余网络tarjan缩点. 考虑一条边(u,v): 当且仅当scc[u] != scc[v], (u,v)可能出现在最小割中...然而我并不会证明 当且仅当scc[u] = scc ...

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

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

  9. 1797: [Ahoi2009]Mincut 最小割

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

随机推荐

  1. ASP.NET各种技巧

    1.动态添加文件框 前台页面关键部分: <script type="text/javascript"> //添加一个选项 function AddFileCtrol() ...

  2. php 单例模式笔记

    <?php /** * 单例模式1. 它们必须拥有一个构造函数,并且必须被标记为private2. 它们拥有一个保存类的实例的静态成员变量3. 它们拥有一个访问这个实例的公共的静态方法单例类不能 ...

  3. phalcon中find 最常用

    1 官网:http://docs.iphalcon.cn/reference/models.html#finding-records 2 具体操作实例 数据: mysql> select * f ...

  4. PHP中可变变量到底有什么用?

    转自:http://blog.csdn.net/engine_1124/article/details/8660291 什么是可变变量? PHP提供了一种其他类型的变量——可变变量.可变变量允许我们动 ...

  5. Mysql--7种Join查询

    0.sql的执行顺序 手写顺序 机读顺序 总结 ①From:对from左边的表和右边的表计算笛卡尔积,产生虚拟表c1 ②On:对c1中的数据进行on过滤,只有符合过滤条件的数据记录才会记录在虚拟表c2 ...

  6. 三十二、MySQL 导出数据

    MySQL 导出数据 MySQL中你可以使用SELECT...INTO OUTFILE语句来简单的导出数据到文本文件上. 使用 SELECT ... INTO OUTFILE 语句导出数据 以下实例中 ...

  7. flock文件锁

    linux中的定时任务crontab会定时执行一些脚本,但是脚本的时间往往无法控制,当脚本的执行时间过长,可能会导致上一次任务的脚本还没执行完,下一次任务的脚本又开始执行的问题.这种情况下会出现一些并 ...

  8. 用随机森林分类器和GBDT进行特征筛选

    一.决策树(类型.节点特征选择的算法原理.优缺点.随机森林算法产生的背景) 1.分类树和回归树 由目标变量是离散的还是连续的来决定的:目标变量是离散的,选择分类树:反之(目标变量是连续的,但自变量可以 ...

  9. 关于debug

    2019-04-05  11:18:15 1. debug 需巧用两个工具 1.1  用‘#’把感觉会出错的代码段注释掉 多行注释有两种快捷操作: 在需要注释的多行代码块前后加一组三引号''' 选中代 ...

  10. python3.7 sys模块

    #!/usr/bin/env python __author__ = "lrtao2010" #python3.7 sys模块 #sys模块负责程序与python解释器的交互,提供 ...