题意是有n座城市,n号城市不想让1号城市可达n号,每条道路有一条毁坏的代价,1号还可以修一条不能毁坏的道路,求n号城市所需的最小代价最大是多少。
毁坏的最小代价就直接求一遍最大流,就是最小割了。而可以修一条不能毁坏的路,需要枚举的这些边就是源集中的点到汇集中的点,我之前的做法是直接找出所有的割边,再枚举每一条割边,在这两个点上加一个流量为无穷大的边再去求最大流,实际上这样连样例的第二个数据都过不了,因为图不保证是连通的,那就有一些源集中的点和汇集中的点本来就不联通,就不存在这样的割边了。发现这个错误后,我就在没有联通的所有边中加了一条cap为0的边,想弥补上面的bug,但是这样的话超时了。奇怪的是,我没有加那些cap为0的点的时候也是超时而不是wa。
所以就找出所有的源点,找出所有的汇点,去除1和n后枚举这些边在原来的基础上去跑最大流,得出来的意义就是如果修的是这条路,所需要的额外的代价。
我自己的代码不知道为什么过不了,可能是模板的问题?
贴两个代码吧,前面是自己的,后面是别人的。
1 #include <iostream> 2 #include <cstdio> 3 #include <fstream> 4 #include <algorithm> 5 #include <cmath> 6 #include <deque> 7 #include <vector> 8 #include <queue> 9 #include <string> 10 #include <cstring> 11 #include <map> 12 #include <stack> 13 #include <set> 14 #define LL long long 15 #define eps 1e-8 16 #define INF 0x3f3f3f3f 17 #define MAXN 105 18 #define OPEN_FILE 19 using namespace std; 20 int S; 21 struct Edge{ 22 int from, to, cap, flow; 23 //Edge(int u, int v, int c, int f) :from(u), to(v), cap(c), flow(f){}; 24 }; 25 vector<Edge> cutset; 26 bool comp(const Edge& a, const Edge& b){ 27 return (a.from < b.from || (a.from == b.from && a.to < b.to)); 28 } 29 struct Dinic{ 30 int n, m, i, s, t; 31 Edge e; 32 vector<Edge> edges; 33 vector<int> G[MAXN]; 34 int d[MAXN], cur[MAXN]; 35 // bool vis[MAXN]; 36 int Q[MAXN * 10]; 37 38 void init(int n){ 39 this->n = n; 40 for (i = 0; i <= n; i++){ 41 G[i].clear(); 42 } 43 edges.clear(); 44 } 45 void AddEdge(int from, int to, int cap){ 46 edges.push_back(Edge{ from, to, cap, 0 }); 47 edges.push_back(Edge{ to, from, 0, 0 }); 48 m = edges.size(); 49 G[from].push_back(m - 2); 50 G[to].push_back(m - 1); 51 } 52 bool BFS(){ 53 // memset(vis, 0, sizeof(vis)); 54 int head = 0, tail = 0; 55 Q[head] = s; 56 memset(d, 0, sizeof(d)); 57 d[s] = 1; 58 S = 0; 59 while (head <= tail){ 60 int x = Q[head++]; 61 for (i = 0; i < G[x].size(); i++){ 62 Edge& e = edges[G[x][i]]; 63 if (d[e.to] == 0 && e.cap > e.flow){ 64 d[e.to] = d[x] + 1; 65 Q[++tail] = e.to; 66 S++; 67 } 68 } 69 } 70 if (d[t] == 0){ 71 return false; 72 } 73 else{ 74 return true; 75 } 76 } 77 int DFS(int x, int a){ 78 if (x == t || a == 0) return a; 79 int flow = 0, f; 80 for (int& i = cur[x]; i < G[x].size(); i++){ 81 Edge& e = edges[G[x][i]]; 82 if (d[x] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap - e.flow))) > 0){ 83 e.flow += f; 84 edges[G[x][i] ^ 1].flow -= f; 85 flow += f; 86 a -= f; 87 if (a == 0) break; 88 } 89 } 90 return flow; 91 } 92 int MaxFlow(int s, int t, int need){ 93 int flow = 0; 94 this->s = s; 95 this->t = t; 96 while (BFS()){ 97 memset(cur, 0, sizeof(cur)); 98 flow += DFS(s, INF); 99 if (flow > need) return flow; 100 } 101 return flow; 102 } 103 }; 104 int n, m; 105 Dinic p, q; 106 int RIGHT[MAXN]; 107 int main() 108 { 109 #ifdef OPEN_FILE 110 freopen("in.txt", "r", stdin); 111 //freopen("out.txt", "w", stdout); 112 #endif // OPEN_FILE 113 int T; 114 scanf("%d", &T); 115 for (int cas = 1; cas <= T; cas++){ 116 scanf("%d%d", &n, &m); 117 p.init(n); 118 int x, y, z; 119 // memset(conn, 0, sizeof(conn)); 120 for (int i = 1; i <= m; i++){ 121 scanf("%d%d%d", &x, &y, &z); 122 p.AddEdge(x, y, z); 123 // conn[x][y] = true; 124 //conn[y][x] = true; 125 } 126 //int res = p.MaxFlow(1, n, INF); 127 //p.AddEdge(2, 3, INF); 128 //q = p; 129 int res = p.MaxFlow(1, n, INF); 130 int cnt = 1; 131 // memset(isR, 0, sizeof(isR)); 132 for (int i = 2; i < n; i++){ 133 if (p.d[i] == 0){ 134 RIGHT[cnt++] = i; 135 } 136 } 137 cnt--; 138 int ans = 0; 139 for (int i = 0; i <= S; i++){ 140 if (p.Q[i] == 1 || p.Q[i] == n) continue; 141 for (int j = 1; j <= cnt; j++){ 142 q = p; 143 q.AddEdge(p.Q[i], RIGHT[j], INF); 144 int o = q.MaxFlow(1, n, INF); 145 ans = max(ans, o); 146 } 147 } 148 // int ans = 0; 149 // for (int i = 0; i < cutset.size(); i++){ 150 // q = p; 151 // q.AddEdge(cutset[i].from, cutset[i].to, INF); 152 // int o = q.MaxFlow(1, n, INF); 153 // ans = max(ans, o); 154 // } 155 printf("%d\n", ans + res); 156 // printf("%d\n", p.MaxFlow(1, n, INF)); 157 } 158 }