网络流应用

CF1264E Beautiful League

CF1264E Beautiful League

先反其道而行之,如果 (A,B,C) 不符合条件,一定有某一个队伍赢了另外两个队。进一步,如果 x 队赢了 cx 局,不满足条件的三元组数量 number=cx(cx1)2。目的就是让这个东西尽量小

现在有一些的比赛结果已经固定,相当于每个 cx 有一个限制:cx[lx,rx]cx=n(n1)2。如果没有这个限制当然可以根据不等式直接取值,但加上限制后似乎没法直接贪心。(不然为什么数据范围这么小呢

改用费用流。每场比赛一个节点,每个队伍一个节点。连这几种边:

1、S 到所有比赛节点连一条容量为 1,花费为 0 的边,代表这场比赛赢家只有一个。

2、每场比赛向对应的两支队伍连边,容量 1,花费 0

3、每支队伍向 Tnpx1 条边,px 为固定的已经赢的场数。每条边的容量为 1,花费为每次多赢一场后 cx(cx1)2 的增量

在这张图上求最小费用最大流就是答案

#include <bits/stdc++.h>
using namespace std;
void read (int &x) {
    char ch = getchar(); x = 0; while (!isdigit(ch)) ch = getchar();
    while (isdigit(ch)) x = x * 10 + ch - 48, ch = getchar();
} const int N = 52, P = N * N, M = N * 600;
int n, m, S, T, tot, k[N][N], c[N], idm[N][N], id[N];
int cnt = 1, h[M], nxt[M], to[M], w[M], co[M];
void add (int u, int v, int ww, int cc) {
    to[++cnt] = v, w[cnt] = ww, co[cnt] = cc, nxt[cnt] = h[u], h[u] = cnt;
    to[++cnt] = u, w[cnt] = 0, co[cnt] = -cc, nxt[cnt] = h[v], h[v] = cnt;
}
queue<int> q; int d[P], f[P], in[P], pre[P];
int spfa () {
    memset (d, 0x3f, sizeof (d));
    memset (in, 0, sizeof (in));
    q.push (S), d[S] = 0, f[S] = 2e9;
    while (!q.empty()) {
        int u = q.front (); q.pop (), in[u] = 0;
        for (int i = h[u], v; i; i = nxt[i])
            if (w[i] && d[v = to[i]] > d[u] + co[i]) {
                d[v] = d[u] + co[i];
                f[v] = min (f[u], w[i]); pre[v] = i;
                if (!in[v]) in[v] = 1, q.push (v);
            }
    }
    return (d[T] != d[T + 1]);
}
void update () {
    for (int x = T, i; x != S; x = to[i ^ 1]) {
        i = pre[x]; w[i] -= f[T], w[i ^ 1] += f[T];
    }
}
signed main() {
    read (n), read (m);
    for (int i = 1, a, b; i <= m; ++i)
        read (a), read (b), k[a][b] = 1, ++c[a];
    for (int i = 1; i <= n; ++i) id[i] = ++tot;
    for (int i = 1; i <= n; ++i)
        for (int j = i + 1; j <= n; ++j)
            if (!k[i][j] && !k[j][i]) {
                idm[i][j] = ++tot; add (0, tot, 1, 0);
                add (tot, id[i], 1, 0); add (tot, id[j], 1, 0);
            }
    S = 0, T = ++tot;
    for (int i = 1; i <= n; ++i)
        for (int j = c[i]; j < n; ++j) add (id[i], T, 1, j);
    while (spfa ()) update ();
    for (int i = 1; i <= n; ++i)
        for (int j = i + 1; j <= n; ++j)
            if (idm[i][j]) {
                int x = idm[i][j], tag = 0, y = 0;
                for (int k = h[x]; k; k = nxt[k])
                    if (to[k] == 0 && w[k] == 1) tag = 1;
                if (!tag) continue;
                for (int k = h[x]; k; k = nxt[k])
                    if (to[k] && w[k] == 0) y = to[k];
                y == i ? k[i][j] = 1 : k[j][i] = 1;
            }
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= n; ++j) putchar (k[i][j] + '0'); puts ("");
    }
}

CF1430G Yet Another DAG Problem(2020-11-10)

CF1430G Yet Another DAG Problem

把边的贡献放到点上,点权的值域和点的个数同级且非常少,把每个点选每个值的贡献当作边权建图

但是有限制,即一条边的 u 的值大于 v 的值。可以在 v 选每个值 p 的地方向 up+1 的地方连 inf

然后求最小割。这个限制相当于如果 v 取了 p,那 up 之前的都是白取,不会算在最小割内

注意点是每条边的权值要平移至正数

CF1354F Summoning Minions(2020-11-14)

CF1354F Summoning Minions

这个题自己想了一半,但最后建图不是像上面那样拆开,没有想出来,但其实dp更简单

先贪心一波,假设最后留下的 k 个点已经选好了,最优方案把这些点按照 bi 排序,前 k1 个在最开始放入,然后随便放入没有选中的点(放入马上删除),最后放入第 k 个点

先假设所有点都没被选中,按照公式算出总答案,用网络流跑选 k 个点的最优解。发现把第 i 个点选成 k 中第 j 个带来的变化是可以算的,这个自然作为边权

与上面不同的是,如果拆开每个点,每个点只能选一次的限制不是很好考虑。其实方法比上面更简单,直接用二分图解决。左部 n 个点为每个点,右部 k 个点为把它选中为第几个,连边跑费用流

ARC107F - Sum of Abs (2020-11-02)

F - Sum of Abs

和上一题比较类似,先把所有的弄成某个状态,然后把改变状态带来的改变价值当作边权,但是这个稍微难理解一些。

一个连通块中,如果总和是负数,相当于所有点的权值 ×1,否则 ×1

在答案中每个点都是被成上了 +11 的权值或被删除,三种状态。限制是没删除的相连的点乘上的值相同

先建立基本的模型,对于每个点拆成 2 个,从源点到第一个点,从第一个点到第二个点,从第二个点到汇点,代表 3 中状态

一开始的答案为所有点的绝对值之和,那么网络流模型中每条边的边权是可以弄出来的。

只剩下添加限制了。设从第一个点连到第二个点的表示删除的代价。对于每条边 (u,v),从 u 的二号点到 v 的一号点连 inf 边,从 v 的二号点到 u 的一号点连 inf

意义就是如果 u 选择删除,v 随意(因为从一号到二号的边已经没了),如果选了 +11v 只能删除或选同样的权值(如果选了不同的两边还是通的,没有意义)。跑最小割就是答案

本文作者:-敲键盘的猫-

本文链接:https://www.cnblogs.com/whx666/p/flow.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   -敲键盘的猫-  阅读(103)  评论(0编辑  收藏  举报
编辑推荐:
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· 一次Java后端服务间歇性响应慢的问题排查记录
· dotnet 源代码生成器分析器入门
· ASP.NET Core 模型验证消息的本地化新姿势
阅读排行:
· 从零开始开发一个 MCP Server!
· ThreeJs-16智慧城市项目(重磅以及未来发展ai)
· .NET 原生驾驭 AI 新基建实战系列(一):向量数据库的应用与畅想
· Ai满嘴顺口溜,想考研?浪费我几个小时
· Browser-use 详细介绍&使用文档
历史上的今天:
2019-03-31 [CF41D] Pawn 题解
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起