最小顶点覆盖,最大独立集,最小边覆盖
点覆盖的概念定义:
对于图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
最小点覆盖+最大独立集(无向图)模板题目:here1,here2
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 }