ZJOI2010 网络容量

    科技2026-02-24  7

    题目链接:https://www.luogu.com.cn/problem/solution/P2604

    这一眼就是网络流题目 第一问十分简单,直接最大流即可 那么怎么做第二问呢?

    我们观察到,先算出了第一问的 m a x f l o w maxflow maxflow,然后第二问等价于在原图中(原图中每条边费用为0),每条边加上一条流量为 ∞ \infty ,费用为原边的费用的图

    然后根据最大流最小费用算法,我们可以知道其实是不用重新建整个图,只需要在当前残量网络中加上原图没有的边即可

    这是因为最大流最小费用算法每次会找出费用最小的一条增广路,我们求最大流时每条增广路费用均为0,一定符合条件

    C o d e Code Code

    #include <iostream> #include <cstdlib> #include <cstdio> #include <cstring> #include <queue> using namespace std; const int MAXN = 1000, MAXM = 1e4, inf = 1 << 30; struct w{int to, nx, f, c;}head[MAXM + MAXM + 10]; struct edge{int x, y, f, c;}e[MAXM + 10]; int a[MAXN + 10], vis[MAXN + 10], dis[MAXN + 10], minf[MAXN + 10], lx[MAXN + 10], tot = 1; inline int read(); inline void add(int x, int y, int i, int f, int c){head[i].to = y, head[i].nx = a[x], head[i].f = f, head[i].c = c; a[x] = i;} inline void add_edge(int x, int y, int f, int c){ add(x, y, ++tot, f, c); add(y, x, ++tot, 0, -c); } bool spfa(int s, int t, int n){ queue <int> q; for (register int i = 1; i <= n; ++i) dis[i] = inf, vis[i] = 0; dis[s] = 0; minf[s] = inf; q.push(s); while (!q.empty()){ int x = q.front(); q.pop(); vis[x] = 0; for (register int i = a[x]; i; i = head[i].nx){ int v = head[i].to; if (head[i].f && dis[v] > dis[x] + head[i].c){ dis[v] = dis[x] + head[i].c; minf[v] = min(minf[x], head[i].f); lx[v] = i; if (!vis[v]){ vis[v] = 1; q.push(v); } } } } return dis[t] < inf; } int MCMF(int s, int t, int n, int op){ int maxflow = 0, mincost = 0; while (spfa(s, t, n)){ maxflow += minf[t]; mincost += dis[t] * minf[t]; int tmp = t; while (tmp != s){ head[lx[tmp]].f -= minf[t]; head[lx[tmp] ^ 1].f += minf[t]; tmp = head[lx[tmp] ^ 1].to; } } if (op) return maxflow; else return mincost; } int main(){ //freopen ("std.in", "r", stdin); //freopen ("std.out", "w", stdout); int n, m, k; n = read(), m = read(), k = read(); for (register int i = 1; i <= m; ++i){ e[i].x = read(), e[i].y =read(), e[i].f = read(), e[i].c = read(); add_edge(e[i].x, e[i].y, e[i].f, 0); } int maxflow = MCMF(1, n, n, 1); printf("%d ", maxflow); add_edge(n + 1, 1, k, 0); for (register int i = 1; i <= m; ++i) add_edge(e[i].x, e[i].y, inf, e[i].c); int mincost = MCMF(n + 1, n, n + 1, 0); printf("%d\n", mincost); return 0; } inline int read(){ int x = 0; char c = getchar(); while (!isdigit(c))c = getchar(); while (isdigit(c))x = (x << 1) + (x << 3) + (c & 15), c = getchar(); return x; }
    Processed: 0.017, SQL: 9