题目1 : 同构
时间限制:2000ms
单点时限:1000ms
内存限制:256MB
描述
给定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
这样。如果树B的任意结构的深度超过2,那么,交叉染色能在A中避免B的出现。 否则当B的深度不超过2,即是两层的树,那么,只要当A中存在一点,它的度数为T1M>=T2M*2-1,就能得到与B相同染色的块。#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N=1000010; int T1[N],T2[N]; int main(){ int T,n,m,u,v,T1M,T2M,icase=0; scanf("%d",&T); while(T--){ scanf("%d",&n); T1M=T2M=0; memset(T1,0,sizeof(int)*(n+10)); for(int i=1;i<n;i++){ scanf("%d%d",&u,&v); T1[u]++; T1[v]++; T1M=max(T1M,max(T1[u],T1[v])); } scanf("%d",&m); memset(T2,0,sizeof(int)*(m+10)); for(int i=1;i<m;i++){ scanf("%d%d",&u,&v); T2[u]++,T2[v]++; T2M=max(T2M,max(T2[u],T2[v])); } printf("Case %d: ",++icase); if(T2M<m-1){ puts("YES"); } else{ if(T1M>=T2M*2-1) puts("NO"); else puts("YES"); } } return 0; }