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;
}
- 版权声明:本文基于《知识共享署名-相同方式共享 3.0 中国大陆许可协议》发布,转载请遵循本协议
- 文章链接:http://www.carlstedt.cn/archives/935 (转载时请注明本文出处及文章链接)


发表评论
快来吐槽一下吧!