全局最小割 Stoer-Wagner (SW算法)优化
优化吃藕了,感谢放宽时限,感谢平板电视 (pb_ds)
#include <iostream> #include <cstdio> #include <cstring> #include <ext/pb_ds/priority_queue.hpp> typedef long long ll; typedef __gnu_pbds::priority_queue<std::pair<int, int>, std::less<std::pair<int, int> >, __gnu_pbds::binomial_heap_tag >pq; struct Edge {int from, to, nxt, val;}; const int maxn = 3e3 + 7; const int maxm = 4e5 + 7; const int inf = 1000000000; int n, r; bool vis[maxn], bin[maxn]; Edge e[maxm * 10 + 7]; int head[maxn], id[maxn][maxn], esz; inline ll read() { int x = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9') {if(ch == '-')f = -1; ch = getchar();} while(ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();} return x * f; } inline void add_edge(int from, int to, int val) { if(id[from][to] == -1) { e[esz].from = from, e[esz].to = to, e[esz].val = val, e[esz].nxt = head[from]; id[from][to] = esz; head[from] = esz++; } else { e[id[from][to]].val += val; } } inline void init() { memset(bin, false, sizeof(bin)); memset(head, -1, sizeof(head)); memset(id, -1, sizeof(id)); esz = 0; } pq que; pq::point_iterator it[maxn]; inline int contract(int &s, int &t) { // Find s,t memset(vis, false, sizeof(vis)); int i, j, k, mincut, maxc; while(!que.empty()) que.pop(); for(i = 1; i <= n; ++i) if(!bin[i])it[i] = que.push(std::make_pair(0, i)); else it[i] = nullptr; for(i = 1; i <= n; i++) { k = -1; maxc = -1; if(que.empty()) return mincut; k = que.top().second, maxc = que.top().first; que.pop(); s = t; t = k; mincut = maxc; vis[k] = true; for(j = head[k]; ~j; j = e[j].nxt) { int v = e[j].to, w = e[j].val; if(!bin[v] && !vis[v]) { que.modify(it[v], std::make_pair((it[v]->first) + w, v)); } } } return mincut; } inline int Stoer_Wagner() { int mincut, i, j, s, t, ans; for(mincut = inf, i = 1; i < n; i++) { ans = contract(s, t); bin[t] = true; if(mincut > ans) mincut = ans; if(mincut == 0)return 0; for(j = 1; j <= n; j++) if(!bin[j]) { if(id[j][t] == -1)continue; if(id[s][j] == -1)add_edge(s, j, e[id[j][t]].val); else e[id[s][j]].val += e[id[j][t]].val; if(id[j][s] == -1)add_edge(j, s, e[id[j][t]].val); else e[id[j][s]].val += e[id[j][t]].val; } } return mincut; } int main() { int m; while(scanf("%d%d", &n, &m) != -1) { init(); for(int i = 1; i <= m; i++) { int a, b, c; a = read(), b = read(), c = read(); add_edge(a, b, c); add_edge(b, a, c); } printf("%d ", Stoer_Wagner()); } return 0; }