编程之美——彩色的树

描述

给定一棵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


分析: 可以用图的深度遍历或者树的深度遍历来解决。

图的遍历
#include<iostream>
#include<vector>
using namespace std;


#define MAXVEX  100000             //最大顶点数,应由用户定义


typedef struct EdgeNode         //边表结点
{
	int adjvex;         //邻接点域,存储该顶点对应的下标	
	struct EdgeNode *next;      //链域,指向下一个邻接点
}EdgeNode;

typedef struct VertexNode       //顶点表结构
{
	int color;        //顶点域,存储顶点信息
	EdgeNode *firstedge;        //边表头指针
}VertexNode, AdjList[MAXVEX];

typedef struct
{
	AdjList adjList;
	int numVertexes, numEdges;  //图中当前顶点数和边数
}GraphList;


//建立图的邻接表结构
void CreateGraph(GraphList *g)
{
	int i, j, k;
	EdgeNode *e;
	EdgeNode *f;
	cin>>g->numVertexes;
	g->numEdges = g->numVertexes-1;

	for(i = 1; i <= g->numVertexes; i++)
	{

		g->adjList[i].color = 0;          //输入顶点信息
		g->adjList[i].firstedge = NULL;          //将边表置为空表
		
	}
	//建立边表
	for(k = 0; k < g->numEdges; k++)
	{
		
		int p,q;
		cin>>p>>q;
		//向内存申请空间,生成边表结点
		e = (EdgeNode *)malloc(sizeof(EdgeNode));
		
		//邻接序号为j
		e->adjvex = q;
		//将e指针指向当前顶点指向的结构
		e->next = g->adjList[p].firstedge;
		//将当前顶点的指针指向e
		g->adjList[p].firstedge = e;

		f = (EdgeNode *)malloc(sizeof(EdgeNode));
		
		f->adjvex = p;
		f->next = g->adjList[q].firstedge;
		g->adjList[q].firstedge = f;
	}
}

bool visited[MAXVEX];

//邻接表的深度递归算法
void DFS(GraphList& g, int i)
{
	EdgeNode *p;
	visited[i] = true;
	p = g.adjList[i].firstedge;
	while(p)
	{
		if(!visited[p->adjvex] && (g.adjList[i].color == g.adjList[p->adjvex].color))
		{
			DFS(g, p->adjvex);           //对访问的邻接顶点递归调用
		}
		p = p->next;
	}
}

//邻接表的深度遍历操作
int DFSTraverse(GraphList& g)
{
	int cnt=0;
	int i;
	for(i = 1; i <= g.numVertexes; i++)
	{
		visited[i] = false;
	}
	for(i = 1; i <= g.numVertexes; i++)
	{
		if(!visited[i])
		{
			DFS(g, i);
			cnt++;
		}
	}

	return cnt;
}



int main()
{
	int T;
	int n;
	int q;
	int x,y;
	int chs;

	vector<vector<int> > vvec;
	vector<int> vec;
	GraphList g;
	cin>>T;

	while(T--)
	{
		vec.clear();
		CreateGraph(&g);
		cin>>q;
		for(int i=0; i<q; i++)
		{
			cin>>chs;
			if(chs==1)
			{
				vec.push_back(DFSTraverse(g));
			}
			if(chs==2)
			{
				cin>>x>>y;
				g.adjList[x].color = y;
			}
		}

		vvec.push_back(vec);

	}


	for(int i=0; i<vvec.size(); i++)
	{
		cout<<"Case #"<<i+1<<":"<<endl;
		for(int j =0; j<vvec[i].size(); j++)
			cout<<vvec[i][j]<<endl;

	}

	return 0;
}

  

树的遍历

#include<iostream>
#include <vector>
const int maxVex = 100000;
using namespace std;

int parent[maxVex];
int child[maxVex];
int color[maxVex];
bool visited[maxVex];
int num; //tree node number

void create()
{
	int x,y;
	cin>>num;
	for (int i=1; i<=num; i++)
	{
		parent[i]=0;
		child[i]=0;
		color[i]=0;
	}
	for(int i=0; i<num-1; i++)
	{
		cin>>x>>y;
		child[x]=y;
		parent[y]=x;
	}
}

void DFS(int i)
{
	visited[i] = true;
	for (int j = child[i]; j<=num&&j>=1&&color[i]==color[j]; j = child[j])
	{
		if(!visited[j])
			DFS(j);
	}

	for (int j = parent[i]; j<=num&&j>=1&&color[i]==color[j]; j = parent[j])
	{
		if(!visited[j])
			DFS(j);
	}
}

int DFSTraverse()
{
	int cnt=0;
	for(int i=1; i<=num; i++)
	{
		visited[i]=false;
	}

	for(int i=1; i<=num; i++)
	{
		if(!visited[i])
		{                                                                                                                                                                                                           
			DFS(i);
			cnt++;
		}
	}
	return cnt;
}


int main()
{
	int T;
	int n;
	int q;
	int x,y;
	int chs;

	vector<vector<int> > vvec;
	vector<int> vec;
	
	cin>>T;

	while(T--)
	{
		vec.clear();
		create();

		cin>>q;
		for(int i=0; i<q; i++)
		{
			cin>>chs;
			if (chs==1)
			{
				vec.push_back(DFSTraverse());
			}
			if(chs==2)
			{
				cin>>x>>y;
				color[x]=y;
			}
		}

		vvec.push_back(vec);
	}


	for(int i=0; i<vvec.size(); i++)
	{
		cout<<"Case #"<<i+1<<":"<<endl;
		for(int j =0; j<vvec[i].size(); j++)
			cout<<vvec[i][j]<<endl;

	}

	return 0;
}


/*


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

*/

  


http://blog.csdn.net/linxinyuluo/article/details/6847851

原文地址:https://www.cnblogs.com/aituming/p/4456339.html