2015编程之美 彩色的树

题目1 : 彩色的树

时间限制:2000ms

单点时限:1000ms

内存限制:256MB

描述

给定一棵n个节点的树,节点编号为1, 2, …, n。树中有n - 1条边,任意两个节点间恰好有一条路径。这是一棵彩色的树,每个节点恰好可以染一种颜色。初始时,所有节点的颜色都为0。现在需要实现两种操作:

1. 改变节点x的颜色为y;

2. 询问整棵树被划分成了多少棵颜色相同的子树。即每棵子树内的节点颜色都相同,而相邻子树的颜色不同。

输入

第一行一个整数T,表示数据组数,以下是T组数据。

每组数据第一行是n,表示树的节点个数。接下来n - 1行每行两个数i和j,表示节点i和j间有一条边。接下来是一个数q,表示操作数。之后q行,每行表示以下两种操作之一:

1. 若为"1",则询问划分的子树个数。

2. 若为"2 x y",则将节点x的颜色改为y。

输出

每组数据的第一行为"Case #X:",X为测试数据编号,从1开始。

接下来的每一行,对于每一个询问,输出一个整数,为划分成的子树个数。

数据范围

1 ≤ T ≤ 20

0 ≤ y ≤ 100000

小数据

1 ≤ n, q ≤ 5000

大数据

1 ≤ n, q ≤ 100000

样例输入

2

3

1 2

2 3

3

1

2 2 1

1

5

1 2

2 3

2 4

2 5

4

1

2 2 1

2 3 2

1

样例输出

Case #1:

1

3

Case #2:

1

5

<span style="font-size:14px;">#include <iostream>
#include <vector>
#include <map>
using namespace std;

//利用hash_map存储边信息,利用vector存储节点的颜色信息, 时间复杂度:O(nlogn)
int main()
{
	int n;
	multimap<int, int> matrix; //存储边的信息
	while(cin>>n)
	{
		//cout<<"n="<<n<<endl;
		for(int i=1; i<=n; i++)
		{
			cout<<"Case #"<<i<<":"<<endl;
			int node_n;
			cin>>node_n;
			//cout<<"node_n="<<node_n<<endl;
			vector<int> node(node_n, 0); //存储节点的颜色值
			int a = 0, b = 0;
			for(int j=0; j<node_n-1; j++)
			{
				cin>>a>>b;
				//cout<<"a="<<a<<", b="<<b<<endl;
				matrix.insert(pair<int, int>(a-1, b-1)); //插入边信息
			}
			//cout<<"matrix.size="<<matrix.size()<<endl;
			int oper_n;
			cin>>oper_n;
			int option = 0;
			int nodeth = 0, color = 0;
			bool no2Flag = false;
			bool again1Flag = false;
			for(int j=0; j<oper_n; j++)
			{
				cin>>option;
				if(option == 1 && !no2Flag) //一直没有节点颜色改变的情况
					cout<<1<<endl;
				else if(option == 1 && no2Flag) //有节点颜色改变的情况下,求划分子树的个数
				{
					int result = 0;
					for(int k=0; k<node_n; k++) //计算划分子树的个数
					{
						bool sameFlag = false; //某节点是否有颜色相同的子节点的标志
						int count = matrix.count(k); //某一节点与子节点的边个数
						multimap<int, int>::iterator iter; //multimap的迭代器
						if(count)
							iter = matrix.find(k); //寻找第一条与子节点的边
						while(count--)
						{
							if(node[k] == node[iter->second]) //母节点与子节点的颜色一样
							{
								sameFlag = true; //记录此节点有颜色相同的相邻节点的标志
								break; //停止此节点与其他子节点的比较
							}
						}
						if(!sameFlag) //此节点没有颜色相同的相邻节点的情况
							result++; //子树个数加1
					}
					cout<<result<<endl;
					again1Flag = true;
				}
				else if(option == 1 && again1Flag) //有节点改变的情况下,连续出现1的命令
					cout<<result<<endl;
				else if(option == 2) //命令为2的情况
				{
					cin>>nodeth>>color;
					node[nodeth-1] = color; //修改此节点的颜色值
					no2Flag = true; //修改节点颜色改变的标志
					again1Flag = false; //不再连续出现1命令
				}
			}
			matrix.clear();
		}
	}
	return 0;
}
</span>
时间: 2024-08-08 08:13:37

2015编程之美 彩色的树的相关文章

2015编程之美初赛第一场 A 彩色的树

时间限制:2000ms 单点时限:1000ms 内存限制:256MB 描述 给定一棵n个节点的树,节点编号为1, 2, -, n.树中有n - 1条边,任意两个节点间恰好有一条路径.这是一棵彩色的树,每个节点恰好可以染一种颜色.初始时,所有节点的颜色都为0.现在需要实现两种操作: 1. 改变节点x的颜色为y: 2. 询问整棵树被划分成了多少棵颜色相同的子树.即每棵子树内的节点颜色都相同,而相邻子树的颜色不同. 输入 第一行一个整数T,表示数据组数,以下是T组数据. 每组数据第一行是n,表示树的节

编程之美2015初赛第一场: 彩色的树

题目1 : 彩色的树 时间限制:2000ms 单点时限:1000ms 内存限制:256MB 描述 给定一棵n个节点的树,节点编号为1, 2, …, n.树中有n - 1条边,任意两个节点间恰好有一条路径.这是一棵彩色的树,每个节点恰好可以染一种颜色.初始时,所有节点的颜色都为0.现在需要实现两种操作: 1. 改变节点x的颜色为y: 2. 询问整棵树被划分成了多少棵颜色相同的子树.即每棵子树内的节点颜色都相同,而相邻子树的颜色不同. 输入 第一行一个整数T,表示数据组数,以下是T组数据. 每组数据

[2015编程之美] 第一场A

#1156 : 彩色的树 时间限制:2000ms 单点时限:1000ms 内存限制:256MB 描述 给定一棵n个节点的树,节点编号为1, 2, …, n.树中有n - 1条边,任意两个节点间恰好有一条路径.这是一棵彩色的树,每个节点恰好可以染一种颜色.初始时,所有节点的颜色都为0.现在需要实现两种操作: 1. 改变节点x的颜色为y: 2. 询问整棵树被划分成了多少棵颜色相同的子树.即每棵子树内的节点颜色都相同,而相邻子树的颜色不同. 输入 第一行一个整数T,表示数据组数,以下是T组数据. 每组

2015编程之美复赛

第一题,不道是什么鬼.. 第二题猜数字. 很多用主席树,我不会,啊啊啊~~~~记得这题有出过吧,想了一发线段树的,把所有的数排序,同时把询问K排序, 做两发遍历,首先从小到大遍历所有的数,单点更新比K小的线段树的点,维护最大值,遇到>=K时则查询一发. 再从大到小遍历,更新比k大的,维护最小值,遇<=K时就查询.比较即可. #include <iostream> #include <cstdio> #include <cstring> #include &l

[2015编程之美] 第一场C

题目3 : 质数相关 时间限制:2000ms 单点时限:1000ms 内存限制:256MB 描述 两个数a和 b (a<b)被称为质数相关,是指a × p = b,这里p是一个质数.一个集合S被称为质数相关,是指S中存在两个质数相关的数,否则称S为质数无关.如{2, 8, 17}质数无关,但{2, 8, 16}, {3, 6}质数相关.现在给定一个集合S,问S的所有质数无关子集中,最大的子集的大小. 输入 第一行为一个数T,为数据组数.之后每组数据包含两行. 第一行为N,为集合S的大小.第二行为

[2015编程之美] 资格赛C

#1150 : 基站选址 时间限制:2000ms 单点时限:1000ms 内存限制:256MB 描述 需要在一个N × M的网格中建立一个通讯基站,通讯基站仅必须建立在格点上. 网格中有A个用户,每个用户的通讯代价是用户到基站欧几里得距离的平方. 网格中还有B个通讯公司,维护基站的代价是基站到最近的一个通讯公司的路程(路程定义为曼哈顿距离). 在网格中建立基站的总代价是用户通讯代价的总和加上维护基站的代价,最小总代价. 输入 第一行为一个整数T,表示数据组数. 每组数据第一行为四个整数:N, M

2015编程之美初赛第三题质数相关

1.解题思路 按题要求,输入数据后先进行是否有两两相同的数据的判断,接着进行从小到大的排序,由于是求质数无关,则集合中任何一对数都不能质数相关,本人采用顺序遍历,将集合中每个数字分为必须包含和必须排外两种情况遍历,首先集合第一个数必须包含,且作为子集中第一个元素,由于是有序数据,只需从集合第二个数遍历起,对加人子集的每个数做质数相关判断(需要遍历一遍),若与子集每个数都质数无关,则将该数纳入该子集,直到遍历完集合后续所有数据,完了统计子集大小:再来第二遍遍历,这是最外循环从大集合第二个数据起,此

2015编程之美 2月29日(求闰年的个数)

<span style="font-size:14px;">// 描述 // 给定两个日期,计算这两个日期之间有多少个2月29日(包括起始日期). // 只有闰年有2月29日,满足以下一个条件的年份为闰年: // 1. 年份能被4整除但不能被100整除 // 2. 年份能被400整除 // 输入 // 第一行为一个整数T,表示数据组数. // 之后每组数据包含两行.每一行格式为"month day, year",表示一个日期.month为{"J

2015编程之美初赛第二场扑克牌

一副不含王的扑克牌由52张牌组成,由红桃.黑桃.梅花.方块4组牌组成,每组13张不同的面值.现在给定52张牌中的若干张,请计算将它们排成一列,相邻的牌面值不同的方案数. 牌的表示方法为XY,其中X为面值,为2.3.4.5.6.7.8.9.T.J.Q.K.A中的一个.Y为花色,为S.H.D.C中的一个.如2S.2H.TD等. 输入 第一行为一个整数T,为数据组数. 之后每组数据占一行.这一行首先包含一个整数N,表示给定的牌的张数,接下来N个由空格分隔的字符串,每个字符串长度为2,表示一张牌.每组数