有下届最小费用可行流模板
Posted Hello,world!
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了有下届最小费用可行流模板相关的知识,希望对你有一定的参考价值。
题目描述:有一个树形的通关图,通过每个关卡需要一定的时间,随时可以停止回到起点重新开始游戏,
问把所有关卡都玩一遍的最少时间
思路:下届为1的最小费用流模板
模板代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> int inf = 1e9 + 7; using namespace std; inline int read() { int re = 0, flag = 1; char ch = getchar(); while (ch > \'9\' || ch < \'0\') { if (ch == \'-\') flag = -1; ch = getchar(); } while (ch >= \'0\' && ch <= \'9\') re = (re << 1) + (re << 3) + ch - \'0\', ch = getchar(); return re * flag; } int n, ans, first[510], cnt = -1; int dis[510], vis[510], q[20010], head, tail; struct edge { int to, next, w, cap; }a[100010]; inline void add(int u, int v, int w, int cap) { a[++cnt] = (edge){ v,first[u],w,cap }; first[u] = cnt; a[++cnt] = (edge){ u,first[v],-w,0 }; first[v] = cnt; } bool spfa(int s, int t) { int i, u, v, w; head = 0, tail = 1; memset(dis, -1, sizeof(dis)); memset(vis, 0, sizeof(vis)); q[0] = t; dis[t] = 0; vis[t] = 1; while (head < tail) { u = q[head++]; vis[u] = 0; for (i = first[u]; ~i; i = a[i].next) { if (!a[i ^ 1].cap) continue; v = a[i].to; w = a[i].w; if (dis[v] == -1 || dis[v] > dis[u] - w) { dis[v] = dis[u] - w; if (!vis[v]) { vis[v] = 1, q[tail++] = v; } } } } return ~dis[s]; } int dfs(int u, int t, int limit) { if (u == t) { vis[t] = 1; return limit; } int i, v, f, flow = 0; vis[u] = 1; for (i = first[u]; ~i; i = a[i].next) { v = a[i].to; if ((dis[v] == dis[u] - a[i].w) && (a[i].cap) && (!vis[v])) { f = dfs(v, t, min(limit, a[i].cap)); if (f) { flow += f; limit -= f; ans += f * a[i].w; a[i].cap -= f; a[i ^ 1].cap += f; if (!limit) return flow; } } } return flow; } int dinic(int s, int t) {//我写的是从某博客上学的改进版zkw费用流 int re = 0; while (spfa(s, t)) { vis[t] = 1; while (vis[t]) { memset(vis, 0, sizeof(vis)); re += dfs(s, t, inf); } } return re; } int d[510]; int main() { memset(first, -1, sizeof(first)); n = read(); int i, t1, t2, t3, j; for (i = 1; i <= n; i++) { t1 = read(); for (j = 1; j <= t1; j++) { t2 = read(); t3 = read(); d[i]--; d[t2]++;//流量下界其实都是一 ans += t3;//加上下届的费用 add(i, t2, t3, inf); } } for (i = 2; i <= n; i++) {//随时可以结束,回到起点 add(i, n + 1, 0, inf); } for (i = 1; i <= n; i++) {//补流过程 if (d[i] > 0) add(0, i, 0, d[i]); if (d[i] < 0) add(i, n + 2, 0, -d[i]); } add(n + 1, 1, 0, inf); dinic(0, n + 2);//最小费用可行流 cout << ans << endl; }
以上是关于有下届最小费用可行流模板的主要内容,如果未能解决你的问题,请参考以下文章