• 二分图匹配--匈牙利算法模板


    对二分图一边的每一个点 dfs ,寻找它的所有匹配点,若那个匹配点没有匹配过或匹配的另一半能新找一个点与之匹配,那么就重组后分别匹配,否则不能匹配

     1 #include<stdio.h>
     2 #include<string.h>
     3 
     4 const int maxn=1e5+5;
     5 const int maxm=1e5+5;
     6 
     7 int head[maxn],point[maxm],nxt[maxm],size;
     8 int match[maxn],vis[maxn];
     9 
    10 void init(){
    11     memset(head,-1,sizeof(head));
    12     size=0;
    13     memset(match,-1,sizeof(match));
    14 }
    15 
    16 void add(int a,int b){
    17     point[size]=b;
    18     nxt[size]=head[a];
    19     head[a]=size++;
    20 }
    21 
    22 int dfs(int s){
    23     for(int i=head[s];~i;i=nxt[i]){
    24         int j=point[i];
    25         if(!vis[j]){
    26             vis[j]=1;
    27             if(match[j]==-1||dfs(match[j])){
    28                 match[j]=s;
    29                 return 1;
    30             }
    31         }
    32     }
    33     return 0;
    34 }
    35 
    36 for(int i=1;i<=n;++i){
    37     memset(vis,0,sizeof(vis));
    38     if(dfs(i)==1)ans++;
    39 }

    然后,关于二分图还有几个个专门的问题:最小路径覆盖和最小点覆盖、二分图的最大独立集

    最小路径覆盖,就是在一个有向无环图中,用最少的路径将所有点覆盖,保证每个点存在且仅存在于一条路径上。

    其做法是将原图中的每个点拆成一个入点和一个出点,对于原图中的每条有向边,在新图中建立出发点的出点到进入点的入点的边,然后对于新图进行二分图最大匹配,而:

    最小路径覆盖数 = 原图的点数 - 最大匹配数

    最小点覆盖数 = 最大匹配数

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

    还有一个问题是二分图关键匹配,即达到最大匹配的必须匹配,可以通过求一遍最大匹配记录下每个点的匹配,然后删去每个匹配时,若不能找到增广路则删去的是关键匹配。

     1 #include<stdio.h>
     2 #include<string.h>
     3 
     4 const int maxn=1e5+5;
     5 const int maxm=1e5+5;
     6 
     7 int head[maxn],point[maxm],nxt[maxm],size;
     8 int match[maxn],vis[maxn];
     9 int get[maxn];
    10 
    11 void init(){
    12     memset(head,-1,sizeof(head));
    13     size=0;
    14     memset(match,-1,sizeof(match));
    15     memset(get,-1,sizeof(get));
    16 }
    17 
    18 void add(int a,int b){
    19     point[size]=b;
    20     nxt[size]=head[a];
    21     head[a]=size++;
    22 }
    23 
    24 int del;
    25 
    26 int dfs(int s,bool F){
    27     for(int i=head[s];~i;i=nxt[i]){
    28         if(!F&&i==del)continue;
    29         int j=point[i];
    30         if(!vis[j]){
    31             vis[j]=1;
    32             if(match[j]==-1||dfs(match[j],F)){
    33                 if(F){
    34                     match[j]=s;
    35                     get[s]=i;
    36                 }
    37                 return 1;
    38             }
    39         }
    40     }
    41     return 0;
    42 }
    43 
    44 
    45         int ans1=0;
    46         for(int i=1;i<=n;++i){
    47             memset(vis,0,sizeof(vis));
    48             if(dfs(i,1))ans1++;
    49         }
    50         int ans=0;
    51         for(int i=1;i<=n;++i){
    52             if(get[i]!=-1){
    53                 del=get[i];
    54                 match[point[del]]=-1;
    55                 get[i]=-1;
    56                 memset(vis,0,sizeof(vis));
    57                 if(!dfs(i,0))ans++;
    58                 get[i]=del;
    59                 match[point[del]]=i;
    60             }
    61         }
  • 相关阅读:
    浏览器工作原理
    Linux内存性能指标、CPU性能指标
    性能结果分析
    javascript事件与event对象的属性
    JavaScript的内置对象和浏览器对象
    互联网协议
    DNS原理
    浏览器缓存知识归纳
    LR性能指标分析
    使用dynatrace+showslow进行前端性能测试
  • 原文地址:https://www.cnblogs.com/cenariusxz/p/4455152.html
Copyright © 2020-2023  润新知