zoukankan      html  css  js  c++  java
  • 二分图板子

    二分图的定义与判定

    I.二分图:设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B)并且图中的每条边(i,j)所关联的两个顶点i和j分别属于这两个不同的顶点集(i in A,j inB)则称图G为二分图. 以上是度娘对二分图的定义,其实我认为太过正规的定义反而不便于理解,不如直接理解对二分图的判定,自然会理解二分图的定义.

    II.判定: 用dfs对图进行黑白染色,当这个点染成黑色时,那与这个点相邻的点染成白色,否则反之.当对所有点进行黑白染色,都未发生逻辑冲突(本来一个点是黑色,但又要它染成白色),那我们成功的将图上所有点分成黑白两个集合,就是上文的集合A,B.可以试着做LGP1330,加深对二分图判断的理解,贴上此题代码.

     1 #include<iostream>
     2 #include<cstdio>
     3 using namespace std;
     4 #define e exit(0)
     5 #define R register
     6 int n,m,from,to,cnt,flag,id,ans,head[10010],vis[10010],color[10010],check[10010];
     7 struct bian{
     8     int to,next;
     9 }len[200010];
    10 void add(int from,int to)
    11 {
    12     len[++cnt].to=to;
    13     len[cnt].next=head[from];
    14     head[from]=cnt;
    15 }
    16 void dfs(int x,int fa,int co)
    17 {
    18     if(flag)
    19         return;
    20     color[x]=co;
    21     for(R int k=head[x];k;k=len[k].next)
    22     {
    23         int to=len[k].to,nowco;
    24         if(to==fa) continue;
    25         if(co==1) nowco=2;
    26         else nowco=1;
    27         if(color[to]&&color[to]!=nowco)
    28         {
    29             flag=1;
    30             return;
    31         }
    32         dfs(to,x,nowco);
    33     }
    34     if(x==id){
    35         int sum1=0,sum2=0;
    36         for(R int i=1;i<=n;++i){
    37             if(!vis[i]||check[i]) continue;
    38             if(color[i]==1){
    39                 ++sum1;
    40                 check[i]=1;
    41             }
    42             else if(color[i]==2){
    43                 ++sum2;
    44                 check[i]=1;
    45             }
    46         }
    47         ans+=min(sum1,sum2);
    48     }
    49 }
    50 int main()
    51 {
    52 //    freopen("s.in","r",stdin);
    53 //    freopen("s.out","w",stdout);
    54     scanf("%d%d",&n,&m);
    55     for(R int i=1;i<=m;++i)
    56     {
    57         scanf("%d%d",&from,&to);
    58         add(from,to),add(to,from);
    59         vis[from]=vis[to]=1;
    60     }
    61     for(R int i=1;i<=n;++i)
    62         if(vis[i]==1&&color[i]==0)
    63         {
    64             id=i;
    65             dfs(i,i,1);
    66         }
    67     if(flag){
    68         printf("Impossible");
    69         return 0;    
    70     }
    71     printf("%d",ans);
    72     return 0;
    73 }

    ②二分图的最大匹配.

    I.定义:对与二分图同一集合没有边相连,但同一集合的点不能连向另一个集合的同一个点,现在我们进行连边操作,问满足要求前提,我们能连多少条边?

    II.方法: 其实求增广路的方法就是一个贪心策略.match数组表示这个点于哪条边相匹配,vis数组表示我们在这一次匹配当中点是否访问过.匹配的过程就是一个贪心的过程,当我们对于一个点匹配时,发现这个点所连的点没有被匹配过就就直接匹配,返回true表示匹配成功,若这个点匹配过我们就对已经匹配这个点的点进行重新匹配,希望找到一个同的点匹配成功,这样我们会得到一条连边 ,匹配失败就换点,要知道每一匹配的子过程都是这样走的,可看做一贪心的协调.vis表示我们在这次匹配中已经访问过了,不论是匹配成功还是失败,它已经进行过贪心,强行将它再拉入这次匹配不会再得到更优匹配.以LG3386为例,上code.

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    using namespace std;
    #define R register
    int n,m,e,ans,check[2010][2010],vis[2010],match[2010];
    bool dfs(int x)
    {
        for(R int j=n + 1;j<=m + n;++j){
            if(!check[x][j]||vis[j]) continue;
            vis[j]=1;
            if(!match[j]||dfs(match[j]))
            {
                match[j]=x;
                match[x]=j;
                return true;
            }
        }
        return false;
    }
    int main()
    {
    //    freopen("s.in","r",stdin);
    //    freopen("s.out","w",stdout);
        scanf("%d%d%d",&n,&m,&e);
        for(R int i=1;i<=e;++i){
            int from,to;
            scanf("%d%d",&from,&to);
            to += n;
            check[from][to]=1;
        }
        memset(match,0,sizeof(match));
        for(R int i=1;i<=n;++i)
        {
            memset(vis,0,sizeof(vis));
            if(!match[i]&&dfs(i))
                ++ans;
        }
        printf("%d",ans);
        return 0;
    }
  • 相关阅读:
    美化WebApi,使其统一返回Json格式
    JavaScript函数封装调用
    Visual Studio 编辑器调试在IIS发布的Web程序出现错误的解决
    C#解析多层Json数据
    Python3解析库lxml
    学习使用Django一 安装虚拟环境
    一:(1.1)了解MVC之路由重写
    Python使用selenium模拟点击,进入下一页(三)
    云服务器安装证书
    Python使用selenium模拟点击(二)
  • 原文地址:https://www.cnblogs.com/xqysckt/p/11254200.html
Copyright © 2011-2022 走看看