zoukankan      html  css  js  c++  java
  • 「CQOI2016」不同的最小割

    「CQOI2016」不同的最小割

    传送门
    建出最小割树,把每一个点对的最小割抠出来 ( ext{unique}) 一下就好了。
    参考代码:

    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    #define rg register
    #define file(x) freopen(x".in", "r", stdin), freopen(x".out", "w", stdout)
    using namespace std;
    template < class T > inline void read(T& s) {
    	s = 0; int f = 0; char c = getchar();
    	while ('0' > c || c > '9') f |= c == '-', c = getchar();
    	while ('0' <= c && c <= '9') s = s * 10 + c - 48, c = getchar();
    	s = f ? -s : s;
    }
    
    const int _ = 850 + 10, __ = 8500 * 2 + 10, INF = 2147483647;
    
    int tot = 1, head[_], Cap[__ << 1], Q[_];
    struct Edge { int ver, cap, nxt; } edge[__ << 1];
    inline void Add_edge(int u, int v, int d) { edge[++tot] = (Edge) { v, d, head[u] }, head[u] = tot ; }
    inline void link(int u, int v, int d) { Add_edge(u, v, d), Cap[tot] = d, Add_edge(v, u, 0), Cap[tot] = 0; }
    
    int n, m, dep[_], cur[_], p[_], t1[_], t2[_];
    int num; struct node { int x, y, z; } G[_];
    int fa[10][_], mn[10][_], len, ans[_ * _];
    
    inline int bfs(int s, int t) {
    	int hd = 0, tl = 0;
    	memset(dep + 1, 0, sizeof (int) * n);
    	Q[++tl] = s, dep[s] = 1;
    	while (hd < tl) {
    		int u = Q[++hd];
    		for (rg int i = head[u]; i; i = edge[i].nxt) {
    			int v = edge[i].ver;
    			if (dep[v] == 0 && edge[i].cap > 0)
    				dep[v] = dep[u] + 1, Q[++tl] = v;
    		}
    	}
    	return dep[t] > 0;
    }
    
    inline int dfs(int u, int flow, int t) {
    	if (u == t) return flow;
    	for (rg int& i = cur[u]; i; i = edge[i].nxt) {
    		int v = edge[i].ver;
    		if (dep[v] == dep[u] + 1 && edge[i].cap > 0) {
    			int res = dfs(v, min(flow, edge[i].cap), t);
    			if (res) { edge[i].cap -= res, edge[i ^ 1].cap += res; return res; }
    		}
    	}
    	return 0;
    }
    
    inline int Dinic(int s, int t) {
    	for (rg int i = 2; i <= tot; ++i) edge[i].cap = Cap[i];
    	int res = 0;
    	while (bfs(s, t)) {
    		for (rg int i = 1; i <= n; ++i) cur[i] = head[i];
    		while (int d = dfs(s, INF, t)) res += d;
    	}
    	return res;
    }
    
    inline void solve(int l, int r) {
    	if (l == r) return ;
    	int s = p[l], t = p[l + 1];
    	G[++num] = (node) { s, t, Dinic(s, t) };
    	int p1 = 0, p2 = 0;
    	for (rg int i = l; i <= r; ++i) if (dep[p[i]]) t1[++p1] = p[i]; else t2[++p2] = p[i];
    	for (rg int i = 1; i <= p1; ++i) p[l + i - 1] = t1[i];
    	for (rg int i = 1; i <= p2; ++i) p[l + p1 + i - 1] = t2[i];
    	solve(l, l + p1 - 1), solve(l + p1, r);
    }
    
    inline void dfs(int u, int f) {
    	dep[u] = dep[f] + 1;
    	for (rg int i = head[u]; i; i = edge[i].nxt) {
    		int v = edge[i].ver; if (v == f) continue ;
    		fa[0][v] = u, mn[0][v] = edge[i].cap, dfs(v, u);
    	}
    }
    
    inline int calc(int x, int y) {
    	int res = INF;
    	if (dep[x] < dep[y]) swap(x, y);
    	for (rg int i = 8; ~i; --i)
    		if (dep[fa[i][x]] >= dep[y]) res = min(res, mn[i][x]), x = fa[i][x];
    	if (x == y) return res;
    	for (rg int i = 8; ~i; --i)
    		if (fa[i][x] != fa[i][y]) res = min(res, min(mn[i][x], mn[i][y])), x = fa[i][x], y = fa[i][y];
    	return min(res, min(mn[0][x], mn[0][y]));
    }
    
    int main() {
    #ifndef ONLINE_JUDGE
    	file("cpp");
    #endif
    	read(n), read(m);
    	tot = 1, memset(head, 0, sizeof head);
    	for (rg int u, v, d; m--; ) read(u), read(v), read(d), link(u, v, d), link(v, u, d);
    	for (rg int i = 1; i <= n; ++i) p[i] = i;
    	num = 0, solve(1, n);
    	tot = 0, memset(head, tot, sizeof head);
    	for (rg int i = 1; i <= num; ++i) Add_edge(G[i].x, G[i].y, G[i].z), Add_edge(G[i].y, G[i].x, G[i].z);
    	fa[0][1] = 0, dfs(1, 0);
    	for (rg int i = 1; i <= 8; ++i)
    		for (rg int u = 1; u <= n; ++u)
    			fa[i][u] = fa[i - 1][fa[i - 1][u]], mn[i][u] = min(mn[i - 1][u], mn[i - 1][fa[i - 1][u]]);
    	for (rg int i = 1; i <= n; ++i) for (rg int j = i + 1; j <= n; ++j) ans[++len] = calc(i, j);
    	sort(ans + 1, ans + len + 1);
    	int QwQ = unique(ans + 1, ans + len + 1) - ans - 1;
    	printf("%d
    ", QwQ);
    	return 0;
    }
    
  • 相关阅读:
    苹果远程推送测试
    iOS 模糊化效果 ANBlurredImageView的使用
    VS2015中正确添加GIF的方式
    十大经典排序算法
    Windows Error Code(windows错误代码详解)
    C++捕获系统异常(VS2015设置)
    Qt5 error LNK2019 无法解析的外部符号的解决办法
    Linux常用命令大全(非常全!!!)
    利用MFC Picture Control控件 加载bmp,png
    在C++中如何实现文件的读写
  • 原文地址:https://www.cnblogs.com/zsbzsb/p/12231718.html
Copyright © 2011-2022 走看看