二分图相关-持续更新

来源:互联网 发布:淘宝图片大小多少和 编辑:程序博客网 时间:2024/05/29 14:44

二分图的若干结论:

最小覆盖要求用最少的点(X集合或Y集合的都行)让每条边都至少和其中一个点关联。

最小覆盖=最大匹配

1.先把最大匹配中每条边抽取一个点,这些点至少覆盖了最大匹配中的边,因此有最大匹配<=最小覆盖(最小覆盖覆盖了所有边所以会比较大)

2.从最小覆盖中构造一个匹配(匹配数=最小覆盖数),设最小覆盖的点为v1,v2,...vn,显然对任意2点vi,vj出发总可以找到2条边e1,e2且e1,e2没有连向同一个点(想想为什么?),所以有最大匹配>=最小覆盖

由1,2得:最小覆盖=最大匹配


独立集:在所有顶点之间选一些点,两两之间无连线。这些点构成一个独立集。

对于二分图:最大独立集(点数最多的独立集)=顶点个数-最小点覆盖(最大匹配),用反证法很容易证。


最小路径覆盖与二分图:记住最小路径覆盖=顶点数-最大匹配

具体见这里


二分图匹配先贴模板:

#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>#include <algorithm>using namespace std;const int maxK = 1005;const int maxn = 1005;int map[maxK][maxK],cx[maxn],cy[maxn],nx,ny,K;bool vis[maxn];int dfs(int s){    for(int i=0; i<ny; i++){        if(!vis[i] && map[s][i]){           vis[i] = 1;           if(cy[i]==-1 || dfs(cy[i])){             cy[i] = s;             cx[s] = i;             return 1;           }        }    }    return 0;}int main(){    while(scanf("%d",&nx)==1 && nx){        scanf("%d%d",&ny,&K);        int i,x,y,z;        memset(map,0,sizeof(map));        memset(cx,-1,sizeof(cx));        memset(cy,-1,sizeof(cy));        for(i=0; i<K; i++){           scanf("%d%d%d",&x,&y,&z);           if(y && z)              map[y][z] = 1;        }        int ans=0;        for(i=0; i<nx; i++)           if(cx[i] == -1){               memset(vis,0,sizeof(vis));               ans += dfs(i);           }        printf("%d\n",ans);    }    return 0;}