1797: [Ahoi2009]Mincut 最小割
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 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
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
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
求最小割的必须边和可行边。
方法是在残量网络上跑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