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