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
  • 相关阅读:
    人月神话阅读笔记01
    梦断代码阅读笔记03
    构建之法阅读笔记03
    构建之法阅读笔记02
    个人课程总结
    第十六周进度总结
    计算最长英语单词链
    第十五周进度总结
    浪潮之巅阅读笔记03
    冲刺2-10
  • 原文地址:https://www.cnblogs.com/jsawz/p/6855307.html
Copyright © 2011-2022 走看看