编程之美 彩色的树

题目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


#include<iostream>
#include <vector>
#include <fstream>

using namespace std;

const int maxVex = 100010;

vector<int> parent[maxVex];
vector<int> child[maxVex];
int color[maxVex];

bool visited[maxVex];
int num;//tree node number
//ifstream in("/Users/urey/data/input");

void create() {
    int x,y;
    cin>>num;
    memset(parent,0,sizeof(parent));
    memset(child,0,sizeof(child));
    memset(color,0,sizeof(color));
    for(int i=1; i<=num-1; i++) {
        cin>>x>>y;
        child[x].push_back(y);//x's child is y
        parent[y].push_back(x);//y's parent is x
    }
}

void dfs(int i) {
    visited[i]=true;
    for(auto j=child[i].begin();j!=child[i].end();j=next(j)) {
        if(*j<=num && *j>=1 && color[*j]==color[i] ) {
            if(!visited[*j]) dfs(*j);
        }
    }
    for(auto j=parent[i].begin();j!=parent[i].end();j=next(j)) {
        if(*j<=num && *j>=1 && color[*j]==color[i] ) {
            if(!visited[*j]) dfs(*j);
        }
    }
}

int dfsTraverse() {
    int ans=0;
    memset(visited,false,sizeof(visited));
    for(int i=1; i<=num; i++) {
        if(!visited[i]) {
            dfs(i);
            ans++;
        }
    }
    return ans;
}


int main() {
    int T,q,x,y,ops;
    cin>>T;
    for(int i=0; i<T; i++) {
        create();
        cin>>q;
        cout<<"Case #"<<i+1<<":"<<endl;
        for(int j=0; j<q; j++) {
            cin>>ops;
            if(ops == 1) {
                cout<<dfsTraverse()<<endl;
            }
            if(ops == 2) {
                cin>>x>>y;
                color[x]=y;
            }
        }
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值