BZOJ3206 [Apio2013]道路费用
2015-05-08 22:38
405 查看
首先我们强制要求几条待定价的边在MST中,建出MST
我们发现这个MST中原来的边是一定要被选上的,所以可以把点缩起来,搞成一棵只有$K$个点的树
然后$2^K$枚举每条边在不在最终的MST中,让在最终MST中的待定价的边尽量大,只需要在Kruskal的时候暴力更新每条边的定价即可
时间复杂度$O(m * logm + 2^K * K^2)$
View Code
我们发现这个MST中原来的边是一定要被选上的,所以可以把点缩起来,搞成一棵只有$K$个点的树
然后$2^K$枚举每条边在不在最终的MST中,让在最终MST中的待定价的边尽量大,只需要在Kruskal的时候暴力更新每条边的定价即可
时间复杂度$O(m * logm + 2^K * K^2)$
/************************************************************** Problem: 3206 User: rausen Language: C++ Result: Accepted Time:8040 ms Memory:8232 kb ****************************************************************/ #include <cstdio> #include <algorithm> using namespace std; typedef long long ll; const int N = 1e5 + 5; const int M = 3e5 + 5; const int K = 25; const int inf = 1e9; inline int read(); struct Edge { int x, y, v; inline void get(int f) { x = read(), y = read(); if (f) v = read(); } inline bool operator < (const Edge &E) const { return v < E.v; } } E[M], Ek[K], s[K]; struct edge { int next, to; edge() {} edge(int _n, int _t) : next(_n), to(_t) {} } e[K << 1]; int first , tot; struct tree_node { int fa, dep, mn; ll v, sum; } tr ; int n, m, k, S, top; int fa[2] ; int root[K], cnt_root; int u[K]; ll ans; inline void Add_Edges(int x, int y) { e[++tot] = edge(first[x], y), first[x] = tot; e[++tot] = edge(first[y], x), first[y] = tot; } int find(int x, int f) { return x == fa[f][x] ? x : fa[f][x] = find(fa[f][x], f); } #define y e[x].to void dp(int p) { int x; tr[p].sum = tr[p].v; for (x = first[p]; x; x = e[x].next) if (y != tr[p].fa) { tr[y].dep = tr[p].dep + 1, tr[y].fa = p; dp(y); tr[p].sum += tr[y].sum; } } #undef y ll work() { static int i, x, y, p; static ll res; for (tot = 0, i = 1; i <= k + 1; ++i) { p = root[i]; fa[0][p] = p; first[p] = tr[p].fa = 0, tr[p].mn = inf; } for (i = 1; i <= k; ++i) if (u[i]) { x = find(Ek[i].x, 0), y = find(Ek[i].y, 0); if (x == y) return 0; fa[0][x] = y; Add_Edges(Ek[i].x, Ek[i].y); } for (i = 1; i <= k; ++i) { x = find(s[i].x, 0), y = find(s[i].y, 0); if (x != y) fa[0][x] = y, Add_Edges(s[i].x, s[i].y); } dp(S); for (i = 1; i <= k; ++i) { x = s[i].x, y = s[i].y; if (tr[x].dep < tr[y].dep) swap(x, y); while (tr[x].dep != tr[y].dep) tr[x].mn = min(tr[x].mn, s[i].v), x = tr[x].fa; while (x != y) { tr[x].mn = min(tr[x].mn, s[i].v); tr[y].mn = min(tr[y].mn, s[i].v); x = tr[x].fa, y = tr[y].fa; } } #define x Ek[i].x #define y Ek[i].y for (res = 0, i = 1; i <= k; ++i) if (u[i]) res += tr[x].dep > tr[y].dep ? tr[x].mn * tr[x].sum : tr[y].mn * tr[y].sum; #undef x #undef y return res; } void dfs(int p) { if (p == k + 1) { ans = max(ans, work()); return; } u[p] = 0, dfs(p + 1); u[p] = 1, dfs(p + 1); } int main() { int i, x, y; n = read(), m = read(), k = read(); for (i = 1; i <= m; ++i) E[i].get(1); for (i = 1; i <= k; ++i) Ek[i].get(0); for (i = 1; i <= n; ++i) tr[i].v = read(); sort(E + 1, E + m + 1); for (i = 1; i <= n; ++i) fa[0][i] = fa[1][i] = i; for (i = 1; i <= k; ++i) fa[0][find(Ek[i].x, 0)] = find(Ek[i].y, 0); #define x E[i].x #define y E[i].y for (i = 1; i <= m; ++i) if (find(x, 0) != find(y, 0)) fa[0][find(x, 0)] = fa[0][find(y, 0)], fa[1][find(x, 1)] = fa[1][find(y, 1)]; #undef x #undef y S = find(1, 1); for (i = 1; i <= n; ++i) if (find(i, 1) != i) tr[find(i, 1)].v += tr[i].v; else root[++cnt_root] = i; #define x Ek[i].x #define y Ek[i].y for (i = 1; i <= k; ++i) x = find(x, 1), y = find(y, 1); #undef x #undef y #define x E[i].x #define y E[i].y for (i = 1; i <= m; ++i) x = find(x, 1), y = find(y, 1); for (i = 1; i <= m; ++i) if (find(x, 1) != find(y, 1)) s[++top] = E[i], fa[1][find(x, 1)] = find(y, 1); #undef x #undef y dfs(1); printf("%lld\n", ans); return 0; } inline int read() { static int x; static char ch; x = 0, ch = getchar(); while (ch < '0' || '9' < ch) ch = getchar(); while ('0' <= ch && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); } return x; }
View Code
相关文章推荐
- [Bzoj3206][Apio2013]道路费用(kruscal)(缩点)
- bzoj3206 [Apio2013]道路费用
- bzoj 3206: [Apio2013]道路费用
- bzoj3206 [Apio2013]道路费用
- bzoj 3206: [Apio2013]道路费用 最小生成树
- bzoj 3206: [Apio2013]道路费用 dfs+最小生成树+并查集
- [BZOJ3206][APIO2013]道路费用(最小生成树)
- bzoj 3206: [Apio2013]道路费用【最小生成树+并查集】
- 3206: [Apio2013]道路费用
- bzoj3206 [Apio2013]道路费用(kruskal+并查集+状压枚举+dfs)
- NKOJ 2784 (APIO 2013) 道路费用(最小生成树+缩点)
- BZOJ3206: [Apio2013]道路费用
- 【C++心路历程30】(APIO2013)道路费用
- bzoj 3624: [Apio2008]免费道路(并查集+生成树+乱搞)
- 【bzoj3624】【apio2008】免费道路
- BZOJ 3205 [Apio2013]机器人 斯坦纳树
- 【bzoj3130】【SDOI2013】【费用流】【最大流】
- BZOJ3130: [Sdoi2013]费用流[最大流 实数二分]
- BZOJ 3130: [Sdoi2013]费用流 网络流+二分
- 【SDOI2013】【BZOJ3130】费用流