1. 首页
  2. 二分匹配

HDU 1151 Air Raid (最小路径覆盖)

1.一个二分图中的最大匹配数等于这个图中的最小点覆盖数

König 定理是一个二分图中很重要的定理,它的意思是,一个二分图中的最大匹配数等于这个图中的最小 点覆盖数。如果你还不知道什么是最小点覆盖,我也在这里说一下:假如选了一个点就相当于覆盖了以它 为端点的所有边,你需要选择最少的点来覆盖所有的边。

2.最小路径覆盖=|G|-最大匹配数  

在一个 N*N 的有向图中,路径覆盖就是在图中找一些路经,使之覆盖了图中的所有顶点,且任何一个顶点 有且只有一条路径与之关联;(如果把这些路径中的每条路径从它的起始点走到它的终点,那么恰好可以经 过图中的每个顶点一次且仅一次);如果不考虑图中存在回路,那么每每条路径就是一个弱连通子集. 由上面可以得出:

1.一个单独的顶点是一条路径;

2.如果存在一路径 p1,p2,……pk,其中 p1 为起点,pk 为终点,那么在覆盖图中,顶点 p1,p2,……pk 不再 与其它的

顶点之间存在有向边.

最小路径覆盖就是找出最小的路径条数,使之成为 G 的一个路径覆盖.  路径覆盖与二分图匹配的关系:最小路径覆盖=|G|-最大匹配数;

3.二分图最大独立集=顶点数-二分图最大匹配

独立集:图中任意两个顶点都不相连的顶点集合。

#include <bits/stdc++.h>

const int MAXN = 5010;//点数的最大值
const int MAXM = 50010;//边数的最大值
struct Edge
{
    int to,next;
} edge[MAXM];

int head[MAXN],tot;

void init()
{
    tot = 0;
    memset(head,-1,sizeof(head));
}

void addedge(int u,int v)
{
    edge[tot].to = v;
    edge[tot].next = head[u];
    head[u] = tot++;
}

int linker[MAXN];
bool used[MAXN];
int uN;

bool dfs(int u)
{
    for(int i = head[u]; i != -1 ; i = edge[i].next)
    {
        int v = edge[i].to;
        if(!used[v])
        {
            used[v] = true;
            if(linker[v] == -1 || dfs(linker[v]))
            {
                linker[v] = u;
                return true;
            }
        }
    }
    return false;
}
int hungary()
{
    int res = 0;
    memset(linker,-1,sizeof(linker));
    for(int u = 1; u <= uN; u++)
    {
        memset(used,false,sizeof(used));
        if(dfs(u))res++;
    }
    return res;
}

int main()
{
    int t;
    std::cin>>t;
    int n,k;
    while(t--)
    {
        std::cin>>n>>k;
        init();
        int u,v;
        while(k--)
        {
            std::cin>>u>>v;
            addedge(u,v);
        }
        uN=n;
        std::cout<<(n-hungary())<<std::endl;

    }

    return 0;
}

 

评分 0, 满分 5 星
0
0
看完收藏一下,下次也能找得到
  • 版权声明:本文基于《知识共享署名-相同方式共享 3.0 中国大陆许可协议》发布,转载请遵循本协议
  • 文章链接:http://www.carlstedt.cn/archives/935 (转载时请注明本文出处及文章链接)
上一篇:
:下一篇

发表评论

gravatar

快来吐槽一下吧!

  1. .01 4:06
  2. .02 1:47
  3. .03 3:39
  4. .04 1:40