zoukankan      html  css  js  c++  java
  • 【交叉染色法判断二分图】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 }
  • 相关阅读:
    JavaScript类属性
    JavaScript实现通过的集合类
    Asp.net mvc自定义Filter简单使用
    [转] js实现html table 行,列锁定
    学习笔记:HTML5 Canvas绘制简单图形
    学习笔记:Asp.Net MVC更新部分页面
    Dom随手记
    页面刷新或关闭前警告
    C# 创建WebServices及调用方法
    常用Web Service汇总(天气预报、时刻表等)
  • 原文地址:https://www.cnblogs.com/L-Excalibur/p/8504840.html
Copyright © 2011-2022 走看看