• 编程之美2015初赛第一场 hihoCoder #1156 : 彩色的树(染色问题)


    
    

    #1156 : 彩色的树




    时间限制: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

    解题步骤:1、求出所有点的父结点,这边用的bfs遍历

                  2、使用一个map<int,int>mp[N],mp[i][j]=k表示第i个结点的颜色是j,并且和它同颜色的儿子结点数为k

                  3、ans开始只有1

                  4、color数组初始化为0

                  5、如果要更新颜色,求出变化的子树数量,更新ans

                  6、至于子树数量的变化,如x的颜色变为y,那么先求出x颜色没变化时的子结点ans0,再求出颜色变化后的子结点ans1,然后ans=ans+ans0-ans1,更新ans

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<vector>
     5 #include<map>
     6 #include<algorithm>
     7 #include<queue>
     8 using namespace std;
     9 #define N 100006
    10 int n;
    11 vector<int> edge[N];//保存边
    12 int fa[N];//记录父节点
    13 map<int,int>mp[N];//mp[i][j]=k表示第i个结点的颜色是j,并且和它同颜色的儿子结点数为k
    14 int color[N];//color用来记录结点的颜色,初始化为0
    15 void bfs()
    16 {
    17     queue<int> q;
    18     q.push(1);
    19     fa[1]=0;
    20     while(!q.empty())
    21     {
    22         int u=q.front();
    23         q.pop();
    24         for(int i=0;i<edge[u].size();i++)
    25         {
    26             int v=edge[u][i];
    27             if(fa[v]!=-1) continue;
    28             fa[v]=u;
    29             q.push(v);
    30         }
    31     }
    32 }
    33 int main()
    34 {
    35     int t;
    36     scanf("%d",&t);
    37     int ac=0;
    38     while(t--)
    39     {
    40         printf("Case #%d:
    ",++ac);
    41         for(int i=0;i<N;i++)edge[i].clear();
    42         memset(fa,-1,sizeof(fa));
    43 
    44         scanf("%d",&n);
    45         for(int i=1;i<n;i++)
    46         {
    47             int u,v;
    48             scanf("%d%d",&u,&v);
    49             edge[u].push_back(v);
    50             edge[v].push_back(u);
    51         }
    52 
    53         bfs();//bfs用来求所有的点的父节点,待会要用到
    54 
    55         for(int i=1;i<=n;i++)
    56         {
    57             mp[i].clear();
    58             color[i]=0;
    59             if(i==1) mp[i][0]=edge[i].size();
    60             else mp[i][0]=edge[i].size()-1;//这边减掉1的原因是i肯定要和1这个根结点相连,所以减1
    61         }
    62         //for(int i=1;i<=n;i++)
    63             //printf("--%d
    ",mp[i][0]);
    64 
    65         int q;
    66         scanf("%d",&q);
    67         int ans=1;
    68         while(q--)
    69         {
    70             int c;
    71             scanf("%d",&c);
    72             if(c==1) printf("%d
    ",ans);//如果是1就输出结果,开始只有一棵
    73             else
    74             {
    75                 int x,y;
    76                 scanf("%d%d",&x,&y);
    77                 int ans0=mp[x][color[x]];//ans0表示还未变色时x的子结点总数
    78                 if(x!=1 && color[fa[x]]==color[x]) ans0++;//如果不是根结点,并且x的父结点和它颜色相同,则++
    79 
    80                 int ans1=mp[x][y];//ans1表示x变完颜色后的子结点个数
    81                 if(x!=1 && color[fa[x]]==y) ans1++;//如果不是根结点,并且x的父结点和它颜色相同,则++
    82 
    83                 ans=ans+ans0-ans1;//ans加上增加的子树
    84 
    85                 if(x!=1)
    86                 {
    87                     mp[fa[x]][color[x]]--;//因为要变色,所以父结点的子结点 -1
    88                     color[x]=y;//将颜色改变
    89                     mp[fa[x]][color[x]]++;//当前颜色的子结点 +1
    90                 }
    91                 color[x]=y;//如果是根节点的话,
    92             }
    93         }
    94     }
    95     return 0;
    96 }
    View Code

     

  • 相关阅读:
    traceroute工作原理
    Android 关于资源适配
    JavaScript对象
    八大排序算法总结
    Linux pipe函数
    cocos2d-x读取xml(适用于cocos2d-x 2.0以上版本号)
    WebService 设计总结
    select poll使用
    QQ强制视频聊天
    图解iPhone开发新手教程
  • 原文地址:https://www.cnblogs.com/UniqueColor/p/4737632.html
Copyright © 2020-2023  润新知