BZOJ 1797: [Ahoi2009]Mincut 最小割

1797: [Ahoi2009]Mincut 最小割

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 2055  Solved: 879
[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

[Submit][Status][Discuss]

 

求最小割的必须边和可行边。

方法是在残量网络上跑Tarjan求出所有的SCC(强连通分量),并对SCC标号。

如果一条满流边满足u和v不属于同一个SCC,则是一条可行边。

如果一条满流边满足u和S属于同一个SCC且v和T属于同一个SCC,则是一条必须边。

所有的必须边一定都是可行边。

 

  1 #include <bits/stdc++.h>
  2 
  3 #define fread_siz 1024 
  4 
  5 inline int get_c(void)
  6 {
  7     static char buf[fread_siz];
  8     static char *head = buf + fread_siz;
  9     static char *tail = buf + fread_siz;
 10     
 11     if (head == tail)
 12         fread(head = buf, 1, fread_siz, stdin);
 13         
 14     return *head++;
 15 }
 16 
 17 inline int get_i(void)
 18 {
 19     register int ret = 0;
 20     register int neg = false;
 21     register int bit = get_c();
 22     
 23     for (; bit < 48; bit = get_c())
 24         if (bit == '-')neg ^= true;
 25         
 26     for (; bit > 47; bit = get_c())
 27         ret = ret * 10 + bit - 48;
 28         
 29     return neg ? -ret : ret;
 30 }
 31 
 32 template <class T>
 33 inline T min(T a, T b)
 34 {
 35     return a < b ? a : b;
 36 }
 37 
 38 #define inf 2e9
 39 #define maxn 200005
 40 
 41 int n, m;
 42 int s, t;
 43 
 44 int edges;
 45 int hd[maxn];
 46 int nt[maxn];
 47 int to[maxn];
 48 int fl[maxn];
 49 
 50 inline void add_edge(int u, int v, int f)
 51 {
 52     nt[edges] = hd[u]; to[edges] = v; fl[edges] = f; hd[u] = edges++;
 53     nt[edges] = hd[v]; to[edges] = u; fl[edges] = 0; hd[v] = edges++;
 54 }
 55 
 56 int dep[maxn];
 57 
 58 inline bool bfs(void)
 59 {
 60     static int que[maxn];
 61     static int head, tail;
 62     
 63     memset(dep, 0, sizeof(dep));
 64     
 65     head = 0, tail = 0;
 66     que[tail++] = s;
 67     dep[s] = 1;
 68     
 69     while (head != tail)
 70     {
 71         int u = que[head++], v;
 72         
 73         for (int i = hd[u]; ~i; i = nt[i])
 74             if (!dep[v = to[i]] && fl[i])
 75             {
 76                 dep[v] = dep[u] + 1;
 77                 que[tail++] = v;
 78             }
 79     }
 80     
 81     return dep[t];
 82 }
 83 
 84 int dfs(int u, int f)
 85 {
 86     if (u == t || !f)
 87         return f;
 88         
 89     int used = 0, flow, v;
 90     
 91     for (int i = hd[u]; ~i; i = nt[i])
 92         if (dep[v = to[i]] == dep[u] + 1)
 93         {
 94             flow = dfs(v, min(f - used, fl[i]));
 95             
 96             used += flow;
 97             fl[i] -= flow;
 98             fl[i^1] += flow;
 99             
100             if (used == f)
101                 return f;
102         }
103         
104     if (!used)
105         dep[u] = 0;
106         
107     return used;
108 }
109 
110 inline bool dfs(void)
111 {
112     return dfs(s, inf) != 0;
113 }
114 
115 inline void max_flow(void)
116 {
117     while (bfs())
118     while (dfs());
119 }
120 
121 int dfn[maxn];
122 int scc[maxn];
123 
124 void tarjan(int u)
125 {
126     static int tim = 0;
127     static int cnt = 0;
128     static int top = 0;
129     static int low[maxn];
130     static int stk[maxn];
131     
132     dfn[stk[++top] = u] = low[u] = ++tim;
133     
134     for (int i = hd[u], v; ~i; i = nt[i])if (fl[i])
135     {
136         if (!dfn[v = to[i]])
137             tarjan(v), low[u] = min(low[u], low[v]);
138         else if (!scc[v])
139             low[u] = min(low[u], dfn[v]);
140     }
141     
142     if (low[u] == dfn[u])
143     {
144         ++cnt; int p;
145         do
146             scc[p = stk[top--]] = cnt;
147         while (p != u);
148     }
149 }
150 
151 signed main(void)
152 {
153     n = get_i();
154     m = get_i();
155     s = get_i();
156     t = get_i();
157     
158     memset(hd, -1, sizeof(hd));
159     
160     for (int i = 1; i <= m; ++i)
161     {
162         int u = get_i();
163         int v = get_i();
164         int w = get_i();
165         add_edge(u, v, w);
166     }
167     
168     max_flow(); 
169     
170     for (int i = 1; i <= n; ++i)
171         if (!dfn[i])tarjan(i);
172         
173     for (int i = 0; i < edges; i += 2)
174     {
175         int u = to[i ^ 1], v = to[i];
176         if (fl[i] || scc[u] == scc[v])
177             puts("0 0");
178         else if (scc[u] == scc[s] && scc[v] == scc[t])
179             puts("1 1");
180         else
181             puts("1 0");
182     }
183 }

 

@Author: YouSiki

posted @ 2016-12-26 10:28  YouSiki  阅读(219)  评论(2编辑  收藏  举报