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;
}