描述
给定2个树A和B,保证A的节点个数>=B的节点个数。
现在你需要对树A的边进行二染色。
一个好的染色方案,指不存在一个树A中的连通块,同时满足以下2个条件
1. 其中只有同色的边
2. 和B同构。两个树同构是指,存在一个一一映射(既是单射又是满射),将树B的各节点映射到不同的树A的节点,使得原来在树B中相邻的点,在映射后,仍相邻。
问是否存在一种好的染色方案。
输入
第一行一个整数T (1<=T<=10),表示数据组数。
接下来是T组输入数据,测试数据之间没有空行。
每组数据格式如下:
第一行一个整数N ,表示树A的节点总数。
接下来N-1行,每行2个数a, b (1 <= a, b <= N)表示树A的节点a和b之间有一条边。
接下来一行,一个整数M(1 <= M <= N),表示树B的节点总数。
接下来M-1行,每行2个数a, b (1 <= a, b <= M)表示树B的节点a和b之间有一条边。
输出
对每组数据,先输出“Case x: ”,x表示是第几组数据,然后接“YES”/“NO”,表示是否存在所求的染色方案。
数据范围
小数据:1 <= N <= 20
大数据:1 <= N <= 1000000
样例解释
无论如何染色,只要从A中挑一条边就行了。
- 样例输入
-
1 3 1 2 2 3 2 1 2
样例输出 -
Case 1: NO
题目解析:
1. 两棵树 A , B ; node(A) >= node(B) ;对 A 二染色,与 B 同构部分不能只有一种颜色。
2.问题转化为:对 A 二染色,颜色相同的部分不能与 B 同构。
3. 举例:
A ————————————> B’
由 A 得出最大边同色树
其中,A 的根结点的度最大为 5 , 则它连接的边必定有 3 条相同(无论如何染色)。而那些与根节点不相关的边,可以任意染色。
若 B 是 B’ 的子树,则答案是 "NO";否则,答案是 "YES"。
由此图,得出样例输入 && 输出:
1
12
1 2
1 3
……
5 12
4
1 2
1 3
1 4
Case 1: NO
4:解题思路:在树 A 中,找出度最大(设为 D)的节点,进而求出树 B’ (1个根节点,(D+1)/2 个叶节点,深度为 1);
判断 B 是否是 B’ 的子树,若是,则 "NO",否 则 "YES"。
code:
1 #include<stdio.h> 2 #include<memory.h> 3 const int MAX = 1e+6 +1; 4 int d1[MAX]; 5 int d2[MAX]; 6 int main(){ 7 int T, M, N; 8 scanf("%d",&T); 9 for(int k = 0; k < T; ++k){ 10 memset(d1, 0, sizeof(d1)); 11 memset(d2, 0, sizeof(d2)); 12 int v1, v2; 13 scanf("%d", &N); 14 for(int i = 1; i < N; ++i){ 15 scanf("%d%d", &v1, &v2); 16 ++d1[v1]; ++d1[v2]; 17 } 18 scanf("%d", &M); 19 for(int i = 1; i < M; ++i){ 20 scanf("%d%d", &v1, &v2); 21 ++d2[v1]; ++d2[v2]; 22 } 23 int D = 0, Mleaf = 0; 24 for(int i = 1; i <= N; ++i){ 25 if(d1[i] > D) D = d1[i]; 26 if(d2[i] == 1) ++Mleaf; 27 } 28 if(M < 3) --Mleaf; // remove root Node 29 if(Mleaf == M - 1 && Mleaf <= (D + 1) / 2) 30 printf("Case %d: NO\n", k+1); 31 else printf("Case %d: YES\n", k+1); 32 } 33 return 0; 34 }