zoukankan      html  css  js  c++  java
  • 最小顶点覆盖,最大独立集,最小边覆盖

    点覆盖的概念定义:

    对于图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 '
    '
     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
    %d
    ",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 '
    '
     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-ans);
    40     return 0;
    41 }
  • 相关阅读:
    Haproxy的安装与配置
    keepalived工作原理和配置说明
    服务器集群与负载均衡基础知识
    Linux磁盘分区与格式化
    第12章 在.NET中操作XML
    第16章 多线程
    第10章 网络编程
    第8章 流和序列化
    关于引用类型作为参数加上ref与不加ref的区别
    第3章 C#中的委托和事件
  • 原文地址:https://www.cnblogs.com/wsy107316/p/13442715.html
Copyright © 2011-2022 走看看