最小顶点覆盖,最大独立集,最小边覆盖

点覆盖的概念定义:

对于图G=(V,E)中的一个点覆盖是一个集合S⊆V使得每一条边至少有一个端点在S中。

最小点覆盖:

实质是个点集,点集里面的点能覆盖所有的边,最小点覆盖就是满足这个要求的点集中点数最小的那个

最小边覆盖:

实质是个边集,这个集合里的边能覆盖所有的点,最小边覆盖是满足这个要求的所有边集中边数最少的一个

这里顶点数等于总的顶点数,是二分图两边的顶点数,不是一边

 二分图中最小点覆盖等于最大匹配数:

证明:所有的边分为匹配的(A)边和不是匹配的边(B),最小点覆盖的点集就是要每条匹配的边两端顶点中的一个,

比如现在有x1-y1属于A,x1-y2属于B,对于x1-y1这条匹配边取x1而不取y1,这样就能覆盖到x1-y2,即B也能覆盖到。

二分图中最小边覆盖=顶点数-最小点覆盖(最大匹配):

证明:设最大匹配数为m,总顶点数为n。为了使边数最少,又因为一条边最多能干掉两个点,所以尽量用边干掉两个点

也就是取有匹配的那些边,当然这些边是越多越好,那就是最大匹配了,所以先用最大匹配数目的边干掉大多数点

剩下的解决没有被匹配的点,就只能一条边干掉一个点了,设这些数目为a

显然,2m+a=n,而最小边覆盖=m+a,

所以最小边覆盖=(2m+a)-m=n-m

二分图中最大独立集=点数-最大匹配数

二分图的最大独立集是:一个最大的点的集合,该集合内的任意两点没有边相连。

二分图最大团的定义是:一个最大的点的集合,该集合内的任意两点都有边相连。

从定义可以看出"二分图的最大独立集"和"二分图补图的最大团"是一样的。

 

来自大佬博客:here

最小点覆盖+最大独立集(无向图)模板题目:here1here2

AC模板:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 #define endl '\n'
 5 const int maxn = 1005;
 6 
 7 vector<int>G[maxn];
 8 bool vis[maxn];
 9 int n,m,match[maxn];
10 
11 bool dfs(int x){
12     int len=G[x].size();
13     for(int i=0;i<len;i++){
14         int nxt=G[x][i];
15         if(!vis[nxt] ){
16             vis[nxt]=true;
17             if( !match[nxt] || dfs(match[nxt])){
18                 match[nxt]=x;
19                 match[x]=nxt;
20                 return true;
21             }
22         }
23     }
24     return false;
25 }
26 
27 int main()
28 {
29     scanf("%d%d",&n,&m);
30     for(int i=1;i<=m;i++){
31         int x,y;
32         scanf("%d%d",&x,&y);
33         G[x].push_back(y);
34         G[y].push_back(x);
35     }
36     int ans=0;
37     for(int i=1;i<=n;i++){
38         memset(vis,false,sizeof(vis));
39         if( !match[i] && dfs(i)) ans++;
40     }
41     printf("%d\n%d\n",ans,n-ans);
42     return 0;
43 }

 最小边覆盖(有向图)AC模板:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 #define endl '\n'
 5 const int maxn = 1005;
 6 
 7 vector<int>G[maxn];
 8 bool vis[maxn];
 9 int n,m,match[maxn];
10 
11 bool dfs(int x){
12     int len=G[x].size();
13     for(int i=0;i<len;i++){
14         int nxt=G[x][i];
15         if(!vis[nxt] ){
16             vis[nxt]=true;
17             if( !match[nxt] || dfs(match[nxt])){
18                 match[nxt]=x;
19                 return true;
20             }
21         }
22     }
23     return false;
24 }
25 
26 int main()
27 {
28     scanf("%d%d",&n,&m);
29     for(int i=1;i<=m;i++){
30         int x,y;
31         scanf("%d%d",&x,&y);
32         G[x].push_back(y);
33     }
34     int ans=0;
35     for(int i=1;i<=n;i++){
36         memset(vis,false,sizeof(vis));
37         if( dfs(i)) ans++;
38     }
39     printf("%d\n",n-ans);
40     return 0;
41 }

 

posted @ 2020-08-05 21:22  swsyya  阅读(1145)  评论(0编辑  收藏  举报

回到顶部