Topcoder SRM 720 Hard
来源:互联网 发布:易语言软件自动更新 编辑:程序博客网 时间:2024/05/29 18:55
链接:
link
题意:
给一个图和两棵树,你要让第一棵树是最小生成树,第二棵树是最大生成树,改变的边权之和最小。
题解:
网络流。
首先可以很容易地转化为一个一般性问题:
记新边权为
记
考虑对于一个给定的
将每个边变成网络流上的一个点,点权为
求出一个最小权闭合子图记为
下面给出证明:
假设存在
由于
最后实际上是
代码:
#include <bits/stdc++.h>#define xx first#define yy second#define mp make_pair#define pb push_back#define mset(x, y) memset(x, y, sizeof x)#define mcpy(x, y) memcpy(x, y, sizeof x)using namespace std;typedef long long LL;typedef pair <int, int> pii;const int MAXN = 1005;const int MAXM = 200005;const int INF = 0x3f3f3f3f;bool edg[MAXN][MAXN], tag[MAXN], chosen[MAXN];int n, m, ql, qr, q[MAXN], dep[MAXN], w[MAXN];vector <pii> adj[MAXN];pii par[MAXN];LL ans;inline void Dfs(int x){ for (auto e : adj[x]) if (e.xx ^ par[x].xx) par[e.xx] = mp(x, e.yy), dep[e.xx] = dep[x] + 1, Dfs(e.xx);}inline void Add(int x, int y, int i, bool t){ if (x == y) return ; if (dep[x] < dep[y]) { if (!t) edg[par[y].yy][i] = 1; else edg[i][par[y].yy] = 1; Add(x, par[y].xx, i, t); } else { if (!t) edg[par[x].yy][i] = 1; else edg[i][par[x].yy] = 1; Add(par[x].xx, y, i, t); }}namespace Flow{ struct Edge { int p, v, w; } e[MAXM << 3]; int e_cnt, S, T, V, ql, qr, q[MAXN], hed[MAXN], dis[MAXN], cur[MAXN]; inline void Init(int n) { V = n; for (int i = 0; i < V; i ++) hed[i] = 0; e_cnt = 1; } inline void Addedge(int x, int y, int w) { e[++ e_cnt] = {y, hed[x], w}; hed[x] = e_cnt; e[++ e_cnt] = {x, hed[y], 0}; hed[y] = e_cnt; } inline bool Bfs() { for (int i = 0; i < V; i ++) dis[i] = 0; dis[q[ql = 0] = S] = qr = 1; while (ql ^ qr) { int x = q[ql ++]; for (int i = hed[x]; i; i = e[i].v) if (e[i].w && !dis[e[i].p]) dis[q[qr ++] = e[i].p] = dis[x] + 1; } return dis[T]; } inline int Dfs(int x, int f) { if (x == T) return f; int ret = 0, t = 0; for (int &i = cur[x]; i; i = e[i].v) if (e[i].w && dis[e[i].p] == dis[x] + 1) { t = Dfs(e[i].p, min(f, e[i].w)); f -= t; ret += t; e[i].w -= t; e[i ^ 1].w += t; if (!f) return ret; } return dis[x] = -1, ret; } inline int Dinic() { int ret = 0; while (Bfs()) { for (int i = 0; i < V; i ++) cur[i] = hed[i]; ret += Dfs(S, INF); } return ret; }}inline void Solve(int l, int r, vector <int> &cur){ if (cur.size() == 0) return ; if (cur.size() == 1) { if (w[cur[0]] < l) ans += l - w[cur[0]]; if (w[cur[0]] > r) ans += w[cur[0]] - r; return ; } if (l == r) { for (auto x : cur) ans += abs(w[x] - l); return ; } int n = cur.size(), mid = l + r >> 1; Flow::Init(n + 2); Flow::S = n, Flow::T = n + 1; for (int i = 0; i < cur.size(); i ++) if (w[cur[i]] > mid) Flow::Addedge(Flow::S, i, 1); else Flow::Addedge(i, Flow::T, 1); for (int i = 0; i < cur.size(); i ++) for (int j = 0; j < cur.size(); j ++) if (edg[cur[i]][cur[j]]) Flow::Addedge(i, j, INF); Flow::Dinic(); for (int i = 0; i < n; i ++) chosen[i] = Flow::dis[i]; vector <int> p, q; for (int i = 0; i < n; i ++) if (chosen[i]) p.pb(cur[i]); else q.pb(cur[i]); Solve(l, mid, q); Solve(mid + 1, r, p);}class ExtremeSpanningTrees{ public: LL minTime(vector <int> a, vector <int> b, vector <int> w, vector <int> m1, vector <int> m2) { n = m1.size() + 1, m = a.size(), ans = 0; mset(edg, 0); for (int i = 0; i < m; i ++) ::w[i] = w[i]; for (int i = 0; i < n; i ++) adj[i].clear(); for (int i = 0; i < m; i ++) tag[i] = 0; for (int i = 0, u, v; i < n - 1; i ++) u = a[m1[i]], v = b[m1[i]], adj[u].pb(mp(v, m1[i])), adj[v].pb(mp(u, m1[i])), tag[m1[i]] = 1; par[0] = mp(-1, -1); Dfs(0); for (int i = 0; i < m; i ++) if (!tag[i]) Add(a[i], b[i], i, 0); for (int i = 0; i < n; i ++) adj[i].clear(); for (int i = 0; i < m; i ++) tag[i] = 0; for (int i = 0, u, v; i < n - 1; i ++) u = a[m2[i]], v = b[m2[i]], adj[u].pb(mp(v, m2[i])), adj[v].pb(mp(u, m2[i])), tag[m2[i]] = 1; par[0] = mp(-1, -1); Dfs(0); for (int i = 0; i < m; i ++) if (!tag[i]) Add(a[i], b[i], i, 1); vector <int> cur; int l = w[0], r = w[0]; for (int i = 0; i < m; i ++) cur.pb(i), l = min(l, w[i]), r = max(r, w[i]); Solve(l, r, cur); return ans; }};
阅读全文
0 0
- Topcoder SRM 720 Hard
- Topcoder SRM 716 Hard
- Topcoder SRM 718 Hard
- Topcoder SRM 726 Hard
- Topcoder SRM 505 Div 2 hard
- Topcoder SRM 663 Div2 Hard: CheeseRolling(状压DP)
- TopCoder SRM 281
- 第一次参加Topcoder SRM
- topcoder SRM 503报告
- topcoder SRM 506
- topcoder SRM 513 DIV2
- Topcoder SRM 495 - 513
- TopCoder SRM 543 DIV2
- topcoder-srm-233-div2
- Topcoder SRM 566 countJourneys
- TopCoder SRM 473 题解
- Topcoder SRM 573 WolfPackDivTwo
- Topcoder SRM Div2 Level2
- git使用_连接远程仓库
- 2017-8-27
- QT tcpsocket 在断开后重新连接程序直接崩溃
- node里面的c-c++模块
- 盒子模型
- Topcoder SRM 720 Hard
- 什么是“怦然心动的感觉”
- [转]nginx 配置详解
- Linux上安装Oracle的辛酸史
- hdu 6140 Hybrid Crystals(数学+思维)
- Springboot ajax异步交互中相关问题
- Java基础题笔记
- 在Win7 64位上使用Python进行TCP通信_Server端
- Android应用开发—通用的GridView网格分割线