BZOJ 4435 [双连通分量][Hash]
2017-07-30 18:50
405 查看
Description
你被雇佣升级一个旧果汁加工厂的橙汁运输系统。系统有管道和节点构成。每条管道都是双向的,且每条管道的流量都是1升每秒。管道可能连接节点,每个节点最多可以连接3条管道。节点的流量是无限的。节点用整数1到n来表示。在升级系统之前,你需要对现有系统进行分析。对于两个不同节点s和t,s→t的流量被定义为:当s为源点,t为汇点,从s能流向t的最大流量。以下面的第一组样例数据为例,1→6的流量为3,1→2的流量为2。计算每一对满足a<b的节点a→b的流量的和。Solution
根据最大流最小割定理,我们要求的其实就是最小割。题中所说每个节点只会连出至多三条边,显然最小割至多为3。分类讨论一下:若最小割为0:说明两点之间不连通。
若最小割为1:说明两点处于不同的双连通分量中。
若最小割为2和3:考虑从图中删去一条边,若删去任何一条边之后两个点仍在同一双连通分量中,则说明最小割为3否则为2。
如何判断删去任意一条边之后的双连通分量编号是否相同,只需要对每个点Hash一下。(注意要是有序的Hash)。
时间复杂度O(n2)。
#include <cstdio> #include <cstring> #include <iostream> using namespace std; inline char get(void) { static char buf[100000], *S = buf, *T = buf; if (S == T) { T = (S = buf) + fread(buf, 1, 100000, stdin); if (S == T) return EOF; } return *S++; } inline void read(int &x) { static char c; x = 0; for (c = get(); c < '0' || c > '9'; c = get()); for (; c >= '0' && c <= '9'; c = get()) x = x * 10 + c - '0'; } const int N = 3030; const int M = 4545; const int P = 2333333; typedef long long ll; struct edge { int to, next; edge (int t = 0, int n = 0):to(t), next(n) {} }; edge G[M << 1]; int pre , low , bcc , sta ; int has , mark[M << 1], id ; int head ; int ans ; int n, m, x, y, Gcnt, clc, top, Bcnt, cnt, Ans; inline int Min(int a, int b) { return a < b ? a : b; } inline void AddEdge(int from, int to) { G[++Gcnt] = edge(to, head[from]); head[from] = Gcnt; G[++Gcnt] = edge(from, head[to]); head[to] = Gcnt; } void dfs(int u, int fa) { low[u] = pre[u] = ++clc; int to; id[u] = cnt; sta[++top] = u; for (int i = head[u]; i; i = G[i].next) if (!mark[i]) { to = G[i].to; if (pre[to]) { if (to != fa) low[u] = Min(low[u], low[to]); } else if (to != fa) { dfs(to, u); low[u] = Min(low[u], low[to]); } } if (low[u] == pre[u]) { Bcnt++; while (sta[top] != u) { bcc[sta[top]] = Bcnt; top--; } bcc[sta[top--]] = Bcnt; } } void SetBcc(int flag = 0) { Bcnt = cnt = clc = top = 0; memset(pre, 0, sizeof pre); memset(id, 0, sizeof id); for (int i = 1; i <= n; i++) if (!pre[i]) { cnt++; dfs(i, 0); } if (flag) return (void)("%%%%gjghfd%%%%"); for (int i = 1; i <= n; i++) has[i] = ((ll)has[i] * M % P + bcc[i]) % P; } int main(void) { freopen("1.in", "r", stdin); freopen("1.out", "w", stdout); read(n); read(m); for (int i = 1; i <= m; i++) { read(x); read(y); AddEdge(x, y); } SetBcc(1); for (int i = 1; i <= n; i++) for (int j = i + 1; j <= n; j++) { if (bcc[i] != bcc[j]) ans[i][j] = 1; if (id[i] != id[j]) ans[i][j] = -1; } for (int i = 1; i <= Gcnt; i += 2) { mark[i] = mark[i + 1] = 1; SetBcc(); mark[i] = mark[i + 1] = 0; } for (int i = 1; i <= n; i++) for (int j = i + 1; j <= n; j++) { if (ans[i][j] != 0) continue; if (has[i] == has[j]) ans[i][j] = 3; else ans[i][j] = 2; } for (int i = 1; i <= n; i++) for (int j = i + 1; j <= n; j++) if (ans[i][j] > 0) Ans += ans[i][j]; cout << Ans << endl; return 0; }
相关文章推荐
- [边双连通分量 Hash] BZOJ 4435 [Cerc2015]Juice Junctions
- 【BZOJ4435】[Cerc2015]Juice Junctions Tarjan+hash
- BZOJ 4435 [Cerc2015]Juice Junctions 分治最小割+hash
- 【BZOJ-4435】Juice Junctions 最小割树(分治+最小割)+Hash
- bzoj4892 [Tjoi2017]dna(SAM/SA/二分答案+Hash)
- BZOJ 3555 [Ctsc2014]企鹅QQ - Hash
- bzoj 3535Fair Photography【hash】
- [BZOJ3555] [Ctsc2014]企鹅QQ(Hash)
- [BZOJ4779] [Usaco2017 Open]Bovine Genomics(hash + 二分)
- bzoj3198 spring hash&容斥原理
- bzoj 3207: 花神的嘲讽计划Ⅰ (主席树+hash)
- BZOJ 1056 [HAOI2008]排名系统 Splay+Hash
- [BZOJ2084][Poi2010]Antisymmetry(hash+二分||manacher)
- 【BZOJ2803】[Poi2012]Prefixuffix【Hash】【单调性】
- 【BZOJ1014】【JSOI2008】火星人prefix Splay处理区间,hash+dichotomy(二分)check出解
- bzoj1014 神奇的平衡树+hash
- BZOJ 4264: 小C找朋友|Hash
- BZOJ 3207 花神的嘲讽计划Ⅰ Hash+可持久化线段树
- bzoj4598 [Sdoi2016]模式字符串(hash+点分治)
- bzoj 1014: [JSOI2008]火星人prefix hash && splay