2020-10-15 dsu on tree

http://icpc.upc.edu.cn/problem.php?cid=2597&pid=10

题目描述

Christmas is still one month away, but Mr. Panda already starts the Christmas preparation. Mr. Panda is decorating a Christmas tree with a set of Russian dolls. There are n Russian dolls numbered 1, 2, . . . , n. The ith doll is designed to be perfected nested inside the i + 1th doll for all 1 ≤ i ≤ n − 1. Nesting dolls are stable only if they have neighboring ordinal numbers, otherwise the smaller one will slide out from the larger one. Dolls can be nested recursively. For example, the n dolls can be nested all the way up from smallest to largest until there is only one doll left.
The Christmas tree happens to have n nodes wit one Russian roll dangling on each node. Doll number 1 is put at the tree root. Mr. Panda will invite his friend Mr. Sheep to collect some dolls from the Christmas tree as gifts on Christmas Eve. Mr. Sheep will pick a tree node and collects all the dolls in the sub-tree with the selected node as the sub-tree root.
As there could be a lot of dolls, Mr. Sheep want to nest the dolls he collects for easy carrying. The dolls should be stably nested. He wonders for each tree node, how many dolls will be ended up if he nests them as much as possible.

输入

The first line of input gives the number of test cases T (1 ≤ T ≤ 10). T test cases follow.
Each test case starts with a line containing an integer n (1 ≤ n ≤ 2 × 105), the number of dolls and also the number of tree nodes.
The next n − 1 lines each contains two integers x and y (1 ≤ x, y ≤ n), denoting doll number x and doll number y are neighbors in the Christmas tree.
It is guaranteed that the sum of n in all cases is not greater than 106.

输出

For each test case, the output consists one line starts with “Case #x:”, where x is the test case number (starting from 1), followed by next n integers. The ith (1 ≤ i ≤ n) integer indicates the number of dolls will be ended up if Mr. Sheep selects tree node that contains doll i, collects all the dolls in the sub-tree,and nests the dolls stably as much as possible.

样例输入
1
7
1 2
2 4
2 6
1 3
3 5
3 7
样例输出
Case #1: 1 3 3 1 1 1 1
解析

dsu on tree算法,详情见:
https://blog.csdn.net/qq_43472263/article/details/104150940

#include <bits/stdc++.h>

using namespace std;
struct node
{
    int from;
    int to;
    int next;
};
vector<node>edge;
int head[200050]= {0};
int hson[200050]= {0};
//int dep[200500]= {0};
//int father[200500]= {0};
int siz[200050]= {0};
int ans[200050]= {0};
int add_edge(int from,int to)
{
    edge.push_back({from,to,head[from]});
    head[from]=edge.size()-1;
}
int dfs1(int now,int depth,int fa)
{
    //dep[now]=depth;
    //father[now]=fa;
    siz[now]=1;
    for(int i=head[now]; i; i=edge[i].next)
    {
        if(edge[i].to!=fa)
        {
            dfs1(edge[i].to,depth+1,now);
            siz[now]+=siz[edge[i].to];
            if(hson[now]==-1||siz[edge[i].to]>siz[hson[now]])
                hson[now]=edge[i].to;
        }
    }
}
bool flag[200050]= {0};
bool vis[200050]= {0};
int cnt=0;
int update(int now,int fa,bool flg)
{
    int sum=flag[now-1]+flag[now+1];
    if(flg) ///插入
    {
        if(sum==2)
            cnt--;
        else if(sum==0)
            cnt++;
    }
    else ///移除
    {
        if(sum==0)
            cnt--;
        else if(sum==2)
            cnt++;
    }
    flag[now]=flg;
    for(int i=head[now]; i; i=edge[i].next)
    {
        if(edge[i].to!=fa&&!vis[edge[i].to])
        {
            update(edge[i].to,now,flg);
        }
    }
}
int dfs2(int now,int fa,bool kep)
{
    for(int i=head[now]; i; i=edge[i].next)
    {
        if(edge[i].to!=fa&&edge[i].to!=hson[now])
        {
            dfs2(edge[i].to,now,false);
        }
    }
    if(hson[now]!=-1)
    {
        dfs2(hson[now],now,true);
        vis[hson[now]]=1;
    }
    update(now,fa,true);
    ans[now]=cnt;
    if(hson[now]!=-1)
        vis[hson[now]]=0;
    if(!kep)
        update(now,fa,false);
}
int main()
{
    int t;
    scanf("%d",&t);
    for(int t1=1; t1<=t; t1++)
    {
        memset(hson,-1,sizeof(hson));
        memset(head,0,sizeof(head));
        edge.clear();
        edge.push_back({-1,-1,-1});
        int n;
        scanf("%d",&n);
        for(int i=1; i<=n-1; i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            add_edge(x,y);
            add_edge(y,x);
        }
        dfs1(1,0,-1);
        memset(flag,0,sizeof(flag));
        memset(vis,0,sizeof(vis));
        dfs2(1,-1,false);
        printf("Case #%d:", t1);
        for(int i=1; i<=n; i++)
            printf(" %d", ans[i]);
        printf("\n");
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值