【BZOJ 3876】【AHOI 2014】支线剧情
2016-12-27 22:02
218 查看
http://www.lydsy.com/JudgeOnline/problem.php?id=3876
这道题每条支线的意思是每条边。。。
那么每条边的下界设为1就行了。
这样建出一个DAG,每条边下界为1,上界为正无穷,赋上费用。设1为S。所有点向T连边,下界为0,上界为正无穷,费用为0,表示可以随时退出。答案是这个图中的最小费用可行流。
最小费用可行流怎么求啊!
可行流什么的我只会求无源汇的。
想了好半天才明白该怎么做。。。
抛弃原来的建图,还是建出一个DAG,每条边下界为1,上界为正无穷,赋上费用。所有非1的点都向1连一条下界为0上界无穷费用为0的边,表示可以随时退出回到1点。
这样就是无源汇的啦!
我们要求这个新的图(附加网络)的最小费用可行流。
可行流我会求(套模板),设超级源S和超级汇T,每个点的入点下界和减去出点下界和,记为di。如果di小于0,从i连边向T,容量为-di;如果di大于0,从S连边向i,容量为di(都是模板的内容~)
从超级源到超级汇跑最大流,跑出来的就是可行流减去下界的流量。因为题意,所以肯定有解;又因为是DAG,所以可行流就是最小流。
如果要求最小费用可行流?不断spfa增广就可以实现最小费用了!
这样对于一条边的流量f=d+g,f为可行流的流量,d为下界,g为附加网络中实际的流量。
求出的最小费用是\(\sum_{i∈E}g_i*w_i\),并不是我们想要的f!
怎么办呢?因为所有的d一定会流满,所以直接加上\(\sum_{i∈E}d_i*w_i\)即可!(我好蠢啊,想了一晚上)
附赠样例图示:
附加网络是介个样子的:
QAQ终于写完了,那么接下来我们
这道题每条支线的意思是每条边。。。
那么每条边的下界设为1就行了。
这样建出一个DAG,每条边下界为1,上界为正无穷,赋上费用。设1为S。所有点向T连边,下界为0,上界为正无穷,费用为0,表示可以随时退出。答案是这个图中的最小费用可行流。
最小费用可行流怎么求啊!
可行流什么的我只会求无源汇的。
想了好半天才明白该怎么做。。。
抛弃原来的建图,还是建出一个DAG,每条边下界为1,上界为正无穷,赋上费用。所有非1的点都向1连一条下界为0上界无穷费用为0的边,表示可以随时退出回到1点。
这样就是无源汇的啦!
我们要求这个新的图(附加网络)的最小费用可行流。
可行流我会求(套模板),设超级源S和超级汇T,每个点的入点下界和减去出点下界和,记为di。如果di小于0,从i连边向T,容量为-di;如果di大于0,从S连边向i,容量为di(都是模板的内容~)
从超级源到超级汇跑最大流,跑出来的就是可行流减去下界的流量。因为题意,所以肯定有解;又因为是DAG,所以可行流就是最小流。
如果要求最小费用可行流?不断spfa增广就可以实现最小费用了!
这样对于一条边的流量f=d+g,f为可行流的流量,d为下界,g为附加网络中实际的流量。
求出的最小费用是\(\sum_{i∈E}g_i*w_i\),并不是我们想要的f!
怎么办呢?因为所有的d一定会流满,所以直接加上\(\sum_{i∈E}d_i*w_i\)即可!(我好蠢啊,想了一晚上)
附赠样例图示:
6 2 2 1 3 2 2 4 3 5 4 2 5 5 6 6 0 0 0
附加网络是介个样子的:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N = 333; const int M = N * N; const int inf = 0x7fffffff; struct node { int nxt, to, c, w, from; } E[M]; int cnt = 1, point ; void ins(int u, int v, int c, int w) { E[++cnt] = (node) {point[u], v, c, w, u}; point[u] = cnt; E[++cnt] = (node) {point[v], u, 0, -w, v}; point[v] = cnt; } bool inq ; int dist , pre , q ; bool spfa(int s, int t) { for (int i = 1; i <= t; ++i) dist[i] = inf; int head = 0, tail = 1, u, v, tt; dist[s] = 0; inq[s] = true; q[1] = s; while (head != tail) { ++head; if (head == N) head = 0; u = q[head]; inq[u] = false; for (int i = point[u]; i; i = E[i].nxt) if (E[i].c && dist[v = E[i].to] > (tt = dist[u] + E[i].w)) { dist[v] = tt; pre[v] = i; if (!inq[v]) { inq[v] = true; ++tail; if (tail == N) tail = 0; q[tail] = v; } } } return dist[t] != inf; } int MCMF(int s, int t) { int ret = 0; while (spfa(s, t)) { int f = inf, u; for (u = t; u != s; u = E[pre[u]].from) f = min(f, E[pre[u]].c); for (u = t; u != s; u = E[pre[u]].from) E[pre[u]].c -= f, E[pre[u] ^ 1].c += f; ret += dist[t] * f; } return ret; } int n, du , S, T, ans = 0; int main() { scanf("%d", &n); for (int i = 1; i <= n; ++i) { int tot, bi, ti; scanf("%d", &tot); du[i] -= tot; while (tot--) { scanf("%d%d", &bi, &ti); ins(i, bi, inf, ti); ++du[bi]; ans += ti; } if (i != 1) ins(i, 1, inf, 0); } S = n + 1; T = S + 1; for (int i = 1; i <= n; ++i) { if (du[i] > 0) ins(S, i, du[i], 0); if (du[i] < 0) ins(i, T, -du[i], 0); } printf("%d\n", MCMF(S, T) + ans); return 0; }
QAQ终于写完了,那么接下来我们
相关文章推荐
- [BZOJ 3876][Ahoi2014]支线剧情:上下界网络流
- bzoj3876 [Ahoi2014]支线剧情
- 【有上下界网络流+费用流多路增广】【bzoj 3876】: [Ahoi2014]支线剧情
- [BZOJ3876][AHOI2014]支线剧情-有下界的最小费用流
- BZOJ 3876: [Ahoi2014]支线剧情【下界费用流
- bzoj3876[AHOI2014]支线剧情(有上下界的费用流)
- 【BZOJ3876】[Ahoi2014]支线剧情 有上下界费用流
- [BZOJ3876][Ahoi2014]支线剧情
- BZOJ-3876-支线剧情-Ahoi2014-上下界网络流
- [bzoj3876][Ahoi2014]支线剧情
- [bzoj3876][AHOI2014]支线剧情 有下界费用流
- BZOJ-3876-支线剧情-Ahoi2014-上下界网络流
- [bzoj3876][AHOI2014]支线剧情——上下界费用流
- 【bzoj3876】[Ahoi2014]支线剧情 有上下界的费用流
- 【bzoj3876】[Ahoi2014]支线剧情 有上下界费用流
- bzoj 3876 [Ahoi2014]支线剧情(有上下界的最小费用流)
- BZOJ 3876 [Ahoi2014]支线剧情
- BZOJ 3876([Ahoi2014]支线剧情-带下界的最小费用可行流)
- bzoj 3876: [Ahoi2014]支线剧情
- 【bzoj3876】【AHOI2014】【支线剧情】【有上下界的费用流】