uva 11396 - Claw Decomposition(二分图判定)

Problem B
Claw Decomposition

Input: Standard Input

Output: Standard Output

A claw is defined as a pointed curved nail on the end of each toe in birds, some reptiles, and some mammals. However, if you are a graph theory enthusiast, you may understand the following special class of graph as shown in the following figure by the word claw.

If you are more concerned about graph theory terminology, you may want to define claw as K1,3.

Let’s leave the definition for the moment & come to the problem. You are given a simple undirected graph in which every vertex has degree 3. You are to figure out whether the graph can be decomposed into claws or not.

Just for the sake of clarity, a decomposition of a graph is a list of subgraphs such that each edge appears in exactly one subgraph in the list.

Input

There will be several cases in the input file. Each case starts with the number of vertices in the graph, V (4<=V<=300). This is followed by a list of edges. Every line in the list has two integers, a & b, the endpoints of an edge (1<=a,b<=V). The edge list ends with a line with a pair of 0. The end of input is denoted by a case with V=0. This case should not be processed.

Output

For every case in the input, print YES if the graph can be decomposed into claws & NO otherwise.

Sample Input Output for Sample Input

4

1 2

1 3

1 4

2 3

2 4

3 4

0 0

6

1 2

1 3

1 6

2 3

2 5

3 4

4 5

4 6

5 6

0 0

0

NO

NO


Problemsetter: Mohammad Mahmudur Rahman

Special Thanks to: Manzurur Rahman Khan

先对题目进行一下分析,要把原图分成若干个“爪”,而每个爪都有三条边,因为题目说明了每条边只能属于一个爪,所以图中边的总数应该是3的倍数,然后从每个点的度数为3,可以得到m*2 == n*3。(m为边数,n为点数),这是对图的边和点数量关系上先进行分析。

那是不是满足这个条件的图就一定是YES呢?如果这样的话,题目给出的每条边的详细信息就没有用上了,从经验上来感觉这种想法是不对的。

只好再深入分析,看到对每个划分出来的爪,如果以它中间的那个点来“标记”这个爪,那另外三个点就只能是它的“附属”,而且这三个点也只能作为其他爪的“附属”,否则是不能满足每条边只属于一个爪的条件的。认识到这一点后,或许会有灵感出现(这里也只能这样解释了),发现所有的爪的“标记”是不会有边相连的,而且所有“附属”也不会相连,这样这整幅图是不是就是我们熟悉的二分图呢?分析到这里,题目也就解决了。回顾来看,这道题对于第一次学习图论的人来说,它的探索过程还是很有趣的,而独立的解答该题的人才能享受到这种乐趣!

#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
using namespace std;

const int maxn = 300 + 5;

int color[maxn];
vector<int> G[maxn];
bool bipartite(int u){
    for(int i = 0;i < G[u].size();i++){
        int v = G[u][i];
        if(color[v] == color[u]) return false;
        if(!color[v]){
            color[v] = 3 - color[u];
            if(!bipartite(v)) return false;
        }
    }
    return true;
}

int main(){
    int n,m;
    while(scanf("%d",&n)){
        if(n == 0) break;
        int a,b;
        m = 0;
        memset(color,0,sizeof(color));
        for(int i = 0;i <= n;i++) G[i].clear();
        while(scanf("%d%d",&a,&b)){
            if(a == 0 && b == 0) break;
            G[a].push_back(b); G[b].push_back(a);
            m++;
        }
        color[1] = 1;//记得先把初始节点的color设为1
        if(m*2 == n*3 && bipartite(1))
            printf("YES\n");
        else
            printf("NO\n");
    }
    return 0;
}


 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值