zoukankan      html  css  js  c++  java
  • 网络流笔记

    几个概念:

    记图G = (V, E)

    匹配:在G中两两没有公共端点的边集M⊆E (我们可以这样理解, 所有的点两两匹配, 自然所有的匹配点之间的边都没有公共点了,最大匹配就是最多能有多少点匹配,最小匹配没有意义)

    边覆盖:G中任意顶点都是边F中某条边的端点的边的集合F⊆G (我们可以这样理解, 用一些边把顶点连起来)

    独立集:在G中两两互不相连的顶点集合M⊆V (我们可以这样理解, 选出一些没有邻居的点)

    顶点覆盖:G中任意边都至少有一个端点属于点集M, M⊆V (我们可以这样理解, 选一些点, 把边都覆盖了)

    1

    对于不存在孤立点的图, |最大匹配|+|最小边覆盖| = |V|

    我们来证明一下:

    首先我们有了最大匹配F⊆E

    那么我们每次选一条边加入F, 这条边最多联通一个顶点, 如果联通了两个, 那么F就不是最大匹配了。

    这样的话, 我们最少需要|V| - 2*|F| 条边覆盖所有顶点 (因为F中每条边都覆盖了两个顶点)(我们每次选一条边, 如果顶点没有全部被覆盖, 每次肯定能覆盖一个新的点, 这挺显然的) 所以我们可以知道|最小边覆盖| = |V| - 2*|F| + |F| = |V| - |F| 所以|最大匹配| + |最小边覆盖| = |V| - |F| + |F| = |V| 证毕

    2

    |最大独立集|+|最小顶点覆盖| = |V|

    首先我们知道, 任意独立集F中每个顶点相邻的边另一侧肯定连接了一个点u∈∁UF(我们想一下, 每条边必定连接了两个顶点, 而且最大独立集中点相邻的边不可能连接两条同时∈F的边, 要不就不是最大独立集了, 那么这些点肯定属于∁UF)我们再任选一条边, 这条边两端的顶点肯定至少有一个顶点u∉F, 也就是u∈∁UF,那么我们就知道了,∁UF中的点能覆盖任意一条边,也就是说∁UF是G的一个顶点覆盖。因为|F|+|∁UF|=|V| 于是我们可以得出|V|-|F|=|∁UF|。

    设∁UF=M,也就是说G的顶点覆盖M有|M|=|V|-|F|。因为|F|为G的任意顶点覆盖,所以我们可以得出:F是G的顶点覆盖-->M是G的边覆盖 因为|M|=|V|-|F| 所以当且仅当F为G最大独立集时M为G的最小顶点覆盖 证毕

    以上问题于是就可以互相转化

    3

    |最大匹配|=|最小顶点覆盖| 二分图中成立 

    因为最大匹配和最大流有关,因此上述四个问题都可以求解了,因此衍生出了很多题目

    4

    补充一些关于二分图的知识,二分图主要应用为二分图匹配

    1.完美匹配:设|F|为图G=(V, E)的一个匹配。 当且仅当2*|F|=|V|时F为图G的一个完美匹配

    2.解法:(1)最大流 (2)匈牙利

    匈牙利算法

    bool dfs(int u)
    {
        used[u] = 1;
        for(int i = head[u]; i; i = e[i].nxt) if(!match[e[i].to] || (!used[match[e[i].to]] && dfs(match[e[i].to])))
        {
            match[e[i].to] = u;
            match[u] = e[i].to;
            return true;
        }
        return false;        
    }
    void solve()
    {
        int ans = 0;
        for(int i = 1; i <= n; ++i) if(!match[i])
        {
            memset(used, 0, sizeof(used));
            if(dfs(i)) ans++;
        }
        printf("%d
    ", ans);
    }
    View Code

    重点在于理解如何实现dfs过程

    对于每个点,如果没有被匹配过,那么我们就要像一个办法让它匹配。

    于是开始dfs,当前点为u,它的后继点为v。当v没有被匹配过,或者v的后继匹配成功了,也就是把v空出来了,那么说明u的匹配成功,match[u]=v,match[v]=u return true 如果所有后继都不可以匹配或者腾出位置,就返回false。used数组是记录当前这个点是否被dfs过,如果dfs过,说明没有dfs这个点的意义。因为我们每次只新加入匹配一个点,因此只要腾出一个位置,那么就是成功的。

    ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    那么我们需要练习一下

    最近做了些网络流

    网络流24题*5

    bzoj 1412最小割

    最小割:s->1 1->2 1->0 0->2 2->T 

    因为我们要把这些点分成两个集合,一些点是羊的范围,一些点是狼的范围,因为要把图分成若干个块,所以空地和空地也要连 

    比如说

    4 1

    1

    0

    0

    2

    空地不连就炸了

    bzoj 1497最小割,也是最大权闭合子图)

    这道题是个很有意思的模型

    建图:ans=sigma(1,m,c[i])

    ins(s,顾客,c) ins(顾客,塔,inf) ins(塔,T,p)

    然后ans-最小割

    若不割左侧 相关右侧都要割
    若不割右侧 相关左侧都要割

    为什么是对的呢?因为我们想要满足一个人,必须买两座塔,那么也就是把塔到T的两条边割掉,如果不满足,那么就把s和顾客的边割掉,对于一个顾客,他到T的路径只有两条,如果我们只割掉一条,剩下两条不割,那么很明显,这个图还可以增广,如果我们割掉两座塔,那么自己的c就肯定不会割掉了,因为到T的路径已经被堵掉了,如果把c割掉了,那么两座塔就可割可不割,因为至少这条道路被割掉了

  • 相关阅读:
    贪心算法与动态规划
    Linux重要目录结构
    博客园添加目录索引
    冒泡排序&插入排序&其他排序
    Linux下部署自己写的Web项目
    Java算法入门-数组&链表&队列
    Java集合-数据结构之栈、队列、数组、链表和红黑树
    Java集合-单例模式斗地主&Collections类的shuffle方法了解
    什么是反向代理服务器
    Linux信号处理
  • 原文地址:https://www.cnblogs.com/19992147orz/p/6493189.html
Copyright © 2011-2022 走看看