zoukankan      html  css  js  c++  java
  • 二分图匹配

    二分图匹配

    之前写过二分图匹配的博客,但就是感觉看了那篇博客也无法真正懂得二分图匹配,所以就再写一篇了。

    先普及一下概念:

    二分图:可以被分为两个子集且保证每个子集中的元素不直接相连的图。

    交替路:从一个未匹配点出发,依次经过未匹配边,匹配边,未匹配边......形成的路径叫做交替路。

    增广路:从一个未匹配点出发,经过交替路,如果途径一个未匹配点,就把走过的路径叫做增广路。

    最大匹配:在一个图的所有匹配中,所含匹配边数最多的匹配,称为这个图的最大匹配。

    完美匹配:一个图的所有顶点都是匹配点,那么这个图就是最大匹配。

    从增广路的定义上我们可以发现,每一条增广路所包含的未匹配点总比匹配点多一个。如果把增广路的所有匹配点变为未匹配点,未匹配点变为匹配点,每进行这样一次操作,未匹配点都会变少一个。我们可以每次在这个图上寻找增广路,然后进行这样的操作,直到在这个图上找不到增广路为止。而进行完这些操作后,所形成的图就是一个最大匹配的图。

    下面用DFS来实现:

     1 #include<cstdio>
     2 #include<cstring>
     3 #define N 42000
     4 int next[N],to[N],num,head[N],vis[N],used[N],n,m,a,b,ans;
     5 void add(int false_from,int false_to){
     6     next[++num]=head[false_from];
     7     to[num]=false_to;
     8     head[false_from]=num;
     9 }
    10 int dfs(int x){
    11     for(int i=head[x];i;i=next[i])
    12         if(!vis[to[i]]){
    13             vis[to[i]]=1;
    14             if(!used[to[i]]||dfs(used[to[i]])){
    15                 used[to[i]]=x;
    16                 return 1;
    17             }
    18         }
    19     return 0;
    20 }
    21 int main(){
    22     scanf("%d%d",&n,&m);
    23     for(int i=1;i<=m;++i){
    24         scanf("%d%d",&a,&b);
    25         add(a,b);
    26         add(b,a);
    27     }
    28     for(int i=1;i<=n;++i)
    29         if(!vis[i]){
    30             memset(used,0,sizeof(used));
    31             if(dfs(i))
    32                 ans++;
    33         }
    34     printf("%d",ans);
    35     return 0;
    36 }
    View Code
  • 相关阅读:
    archlinux .bash_history
    Ubuntu环境下挂载新硬盘
    软碟通 UltraISO U启替代品 Win32DiskImager 无设备 无盘符 无u盘 无优盘 解决方案 之diskpart
    delphi Integer overflow
    MSBuild Tools offline
    delphi synedit免费的拼写检查器dll
    git 自定义命令行
    lua编译
    gcc ar
    Windows Subsystem for Linux (WSL)挂载移动硬盘U盘 卸载 c d 盘
  • 原文地址:https://www.cnblogs.com/jsawz/p/6855307.html
Copyright © 2011-2022 走看看