[BZOJ 3691] 游行
2016-07-12 09:35
218 查看
http://www.lydsy.com/JudgeOnline/problem.php?id=3691
Solution :
被这题折磨了好多天了。。。问了问学长。。。惊讶的发现wmd写过题解。。。。。。我。。。。。
首先我们跑一发floyd。。。算出任意两点最短路。。。于是我们可以假设路径不相交。。。然后。。。往最小点覆盖方向想一想。。。发现一个匹配模型。。。我每次询问都想把C加入图里强行算一遍。。。然后就做不下去了。。。
正解需要灵光一现一下。。。实际上根本没有必要把C加入图里。。。有几个点没有被覆盖。。我们就需要支付几个C。。。于是我们初始化的时候跑一次费用流,记录下每增广一点流量的时候的cost。。。必然单调。。所以对于每次讯问。。。我们在cost数组里二分出一个位置。。cost之前的增广。。。cost之后的支付C。。。容易发现这是最优的。。。
想通这些就去码了。。。数组开大 1 A 了。。。爽啊。。。
Solution :
被这题折磨了好多天了。。。问了问学长。。。惊讶的发现wmd写过题解。。。。。。我。。。。。
首先我们跑一发floyd。。。算出任意两点最短路。。。于是我们可以假设路径不相交。。。然后。。。往最小点覆盖方向想一想。。。发现一个匹配模型。。。我每次询问都想把C加入图里强行算一遍。。。然后就做不下去了。。。
正解需要灵光一现一下。。。实际上根本没有必要把C加入图里。。。有几个点没有被覆盖。。我们就需要支付几个C。。。于是我们初始化的时候跑一次费用流,记录下每增广一点流量的时候的cost。。。必然单调。。所以对于每次讯问。。。我们在cost数组里二分出一个位置。。cost之前的增广。。。cost之后的支付C。。。容易发现这是最优的。。。
想通这些就去码了。。。数组开大 1 A 了。。。爽啊。。。
#include <cstdio> #include <cstring> #include <cstdlib> #define rep(i, x, y) for (int i = (x), _ = (y); i <= _; ++i) #define down(i, x, y) for (int i = (x), _ = (y); i >= _; --i) #define x first #define y second using namespace std; typedef long long LL; template<typename T> inline void upmax(T & x, T y) { x < y ? x = y : 0; } template<typename T> inline void upmin(T & x, T y) { x > y ? x = y : 0; } template<typename T> inline void read(T & x) { char c; while ((c = getchar()) < '0' || c > '9') ; for (x = c - '0'; (c = getchar()) >= '0' && c <= '9'; x = x * 10 - '0' + c) ; } const int inf = 0x3f3f3f3f; const int N = 511; const int M = 1e5 + 10; struct edge { int to, c, w, n; } e[M * 2]; int head , tot = 1; inline void addEdge(int x, int y, int c, int w) { e[++tot] = (edge) {y, c, w, head[x]}, head[x] = tot; e[++tot] = (edge) {x, 0, -w, head[y]}, head[y] = tot; } int pa , d , S, T; bool SPFA() { static bool inq ; static int que[N + 5], fir, las; fir = las = 0; memset(d, 0x3f, sizeof(int) * (T + 5)); d[S] = 0; que[++las] = S; while (fir != las) { int u = que[++fir]; fir == N ? fir = 0 : 0; inq[u] = 0; for (int p = head[u]; p; p = e[p].n) if (e[p].c) { int to = e[p].to; if (d[to] > d[u] + e[p].w) { pa[to] = p; d[to] = d[u] + e[p].w; if (!inq[to]) { inq[to] = 1; que[++las] = to; las == N ? las = 0 : 0; } } } } return d[T] < inf; } int augment() { int x = T, a = inf; while (x != S) { upmin(a, e[pa[x]].c); x = e[pa[x] ^ 1].to; } x = T; while (x != S) { e[pa[x]].c -= a; e[pa[x] ^ 1].c += a; x = e[pa[x] ^ 1].to; } return d[T] * a; } int f ; int cost , sum , cnt; int main() { #ifdef LX_JUDGE freopen("in.txt", "r", stdin); #endif int n, m, Q; read(n), read(m), read(Q); S = 0, T = n + n + 1; memset(f, 0x3f, sizeof(f)); int x, y, w; rep (i, 1, m) { read(x), read(y), read(w); upmin(f[x][y], w); } rep (k, 1, n) rep (i, 1, n) rep (j, 1, n) upmin(f[i][j], f[i][k] + f[k][j]); rep (i, 1, n) { addEdge(S, i, 1, 0); addEdge(i + n, T, 1, 0); } rep (i, 1, n) rep (j, 1, n) if (f[i][j] < inf) addEdge(i, j + n, 1, f[i][j]); while (SPFA()) cost[++cnt] = augment(); rep (i, 1, cnt) sum[i] = sum[i - 1] + cost[i]; int C, l, r; while (Q--) { read(C); l = 0, r = cnt; while (l <= r) { int mid = (l + r) >> 1; cost[mid] < C ? l = mid + 1 : r = mid - 1; } printf("%d\n", sum[r] + C * (n - r)); } fclose(stdin); fclose(stdout); return 0; }
相关文章推荐
- 这是一个看脸的时代,但最终拼的是实力
- 【ReactNative】react native 中es6语法解析
- poj 2325 Persistent Numbers
- Chrome 插件收集
- (LeetCode)Intersection of Two Arrays --- ???
- 10.5 搜索的优化版
- JAVA正则表达式语法大全
- Cookie 的路径以及 Cookie 域
- Hadoop简单介绍
- SPI总线协议及SPI时序图详解
- 微信分享等api笔记
- 通过JDBC进行简单的增删改查(以MySQL为例)
- 【SSH】利用applicationContext.xml文件结合java代码生成项目所需的数据库
- 无限滚动AdapterViews and RecyclerView
- Android Studio系列教程四--Gradle基础
- IOS Dev Intro - Message Transfer Mechanism
- OC 中 NSLog 函数输出格式
- C#正则表达式转义字符介绍
- socket编程总结(一)getaddrinfo()函数详解
- php实现的debug log日志操作类实例