网络流入门 -- 2020.7.20 - 2020.7.25

网络流

Dinic 解最大流

还真是,这个算法不用太懂…直接add然后run就行,难点在建图,奥还有读题…
板子放最后

POJ 1149 PIGS

多源多汇 , 因为猪在猪圈里可以随意更改,所以对每一个猪圈,有一个人拿了出来之后,能转交给其他所有有这个钥匙的人任意数量的猪,最后所有人连上汇点,权重为这个人的需求即可

HDU 3416 Marriage Match IV (Dijkstra+最大流)

问题是求 从S到T的不经过同一条边的最短路数量,可以分成下面几个小问题

  • 如何判断边是否在最短路径上?

    最短路径满足条件是对现在的所有 [u->v] 边 都有: d[u] + cost <= d[v]
    明显当 d[u] + cost == d[v] 时, [u->v] 的这条边在最短路径上

  • 如何计数?

    冷静分析一波 , 假设现在就只有两个点 要计算 a->b 的 不经过同一个边最短路数量,那就是要计算 a->b 的边中有多少个和最小边相同的边数.可以发现,最短路上的权值不影响最后的计数了. 那么推展到n个结点 ,答案就是以最短路径建权值都是1的图,从 S->T的 最大流.

  • 扩展 :当题目要求为不经过相同结点时怎么计数?

    问题转化为结点容量为1 ,从S->T的最大流 ,拆点, 将路径上的每个点拆成 i 和 i+n 加权为1的边即可.

Dinic 解二分图匹配

HDU - 4292 Food

因为每个人只能满意一次,要把人拆点,从源点到人的边权为食物,从人到汇点的边权为饮料

//vector存边,queue操作较慢
const ll inf = 0x3f3f3f3f;
const ll maxn = 1e5 + 7;

struct Dinic
{
   
    struct edge
    {
   
        int to, cap, rev;
        edge(int a, int b, int c)
        {
   
            to = a, cap = b, rev = c;
        }
    };
    vector<edge> G[maxn];
    int level[maxn];
    int iter[maxn];
    void init(int n)
    {
   
        memset(level, 0, sizeof level);
        memset(iter, 0, sizeof iter);
        for (int i = 0; i <= n; i++)
            G[i].clear();
    }
    void add(int from, int to, int cap)
    {
   
        G[from].push_back(edge(to, cap, G[to].size()));
        G[to].push_back(edge(from, 0, G[from].size() - 1));
    }
    void bfs(
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值