二分图相关-持续更新

二分图的若干结论:

最小覆盖要求用最少的点(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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值