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 (转载时请注明本文出处及文章链接)
发表评论
快来吐槽一下吧!