• 【交叉染色法判断二分图】Claw Decomposition UVA


    题目链接:https://cn.vjudge.net/contest/209473#problem/C

    先谈一下二分图相关:

    一个图是二分图的充分必要条件:
    该图对应无向图的所有回路必定是偶环(构成该环形的边的数量为偶数)。
    暂时不证明,后证。

    那么怎么判断一个图的回路是奇环还是偶环呢?

    交叉染色法。

    随机选择一个点,染成红色,把所有跟它相邻的点染成绿色,再由被染色的绿点出发,把相邻的点染成红色……

    即对于一个点和他相邻的点(两个点之间有边相连叫做相邻),颜色必定不同,如果相同,那么是奇环。

    例如1(红)--2(绿)--3(红)--4(绿)--5(红),颜色是跳跃性相同的,如果是奇环那么一定会出现相邻两点颜色相同的情况。

    下面放代码:

    bool _dfs(int u){
        
        int v;
        for(int i=0;i<g[u].size();i++){
            v=g[u][i];
            if(color[v]==color[u])return false;
            else if(!color[v]){
                color[v]=color[u]^1;
                if(!_dfs(v))return false;
            }
        }
        return true;
    }

    回归题目。

    题目大意:给出一个图,这个图上的每个点的度数都为3,判断这个图可不可以拆分成“爪”字形。也就是所有的边都要用上,并且只用一次,点可以无限使用(至少使用一次),把原图拆分成全为

    这种样子的子图。(注意是打散之后!只有这一个样子没有其他连边了!!!)

    解题思路:

    借助了一下别人的智慧orz。对于题目进行分析,我们能够发现每个点只有两种用法:1、一个“爪”的中心点。2、一个“爪”的旁支。两个条件绝对不可能同时满足,(证明:如果该点满足1,那么从这个点出发的三条边就是延伸边,不可能作为辅助边。如果该点满足2,那么从这个点出发的至少有一条边是辅助边,那么剩下的少于三条边不足以支撑这个点变为爪中心。)

    有了这个前提,我们就能很容易地想到二分图两个集合的互斥,那么对于每个点,在和他相连的另一个点上连边,判断一下是否构成二分图就可以了。

    (为什么能构成二分图就有解?一个点如果被规定为爪中心,那么它在跟它相连的三个点全为旁支的情况下,是一定能成立的。【关键在于度数全为3】;一个点如果被规定为旁支,那么跟它相连的所有点都必定是爪中心,所以它的三条边也能分配完毕。)

    坑点:

    图可能不连通。

    下面放上0msAC代码:

     1 #include<stdio.h>
     2 #include<string.h>
     3 #define MAXN 305
     4 
     5 int n,g[MAXN][MAXN],color[MAXN];
     6 
     7 bool _dfs(int p,int t){
     8     
     9     int i;
    10     color[p]=t;
    11     for(i=1;i<=n;i++)
    12         if(g[p][i]){
    13             if(color[i]==t)return false;
    14             if(!color[i])
    15                 if(!_dfs(i,t^1))return false;
    16                 
    17         }
    18     return true;
    19 }
    20 
    21 int main(){
    22 
    23     int x,y,i;
    24     while(true){
    25         scanf("%d",&n); 
    26         if(!n)break;
    27         memset(g,0,sizeof(g));
    28         memset(color,0,sizeof(color));
    29         while(true){
    30             scanf("%d%d",&x,&y);
    31             if(x+y==0)break;
    32             g[x][y]=g[y][x]=true;
    33         }
    34         for(i=1;i<=n;i++)
    35             if(!color[i])
    36                 if(!_dfs(i,2))break;
    37         if(i>n)puts("YES");
    38         else puts("NO");
    39     }
    40     return 0;
    41 }
  • 相关阅读:
    linux下shell显示-bash-4.1#不显示路径解决方法
    node 封装db层
    json结构更改的方法 把date有数据的分类
    webpack.config.js
    SQLSERVER 跨服 跨库
    sqlserver2005重新安装(安装汇编错误,安装程序无法连接到数据库服务进行服务配置)
    delete语句与reference约束 FK_subplan_job_id冲突问题,导致job无法删除解决办法
    删除作业计划出错(DELETE语句与 REFERENCE约束"FK_subplan_job_id"冲突。)
    jquery判断checked的三种方法
    SQLSERVER和sybase的差异
  • 原文地址:https://www.cnblogs.com/L-Excalibur/p/8504840.html
Copyright © 2020-2023  润新知