Codeforces G. Ciel the Commander

题目描述:

Ciel the Commander

time limit per test

1 second

memory limit per test

256 megabytes

input

standard input

output

standard output

Now Fox Ciel becomes a commander of Tree Land. Tree Land, like its name said, has n cities connected by n?-?1 undirected roads, and for any two cities there always exists a path between them.

Fox Ciel needs to assign an officer to each city. Each officer has a rank — a letter from ‘A‘ to ‘Z‘. So there will be 26 different ranks, and ‘A‘ is the topmost, so ‘Z‘ is the bottommost.

There are enough officers of each rank. But there is a special rule must obey: if x and y are two distinct cities and their officers have the same rank, then on the simple path between x and y there must be a city z that has an officer with higher rank. The rule guarantee that a communications between same rank officers will be monitored by higher rank officer.

Help Ciel to make a valid plan, and if it‘s impossible, output "Impossible!".

Input

The first line contains an integer n (2?≤?n?≤?105) — the number of cities in Tree Land.

Each of the following n?-?1 lines contains two integers a and b (1?≤?a,?b?≤?n,?a?≠?b) — they mean that there will be an undirected road between a and b. Consider all the cities are numbered from 1 to n.

It guaranteed that the given graph will be a tree.

Output

If there is a valid plane, output n space-separated characters in a line — i-th character is the rank of officer in the city with number i.

Otherwise output "Impossible!".

Examples

Input

Copy

4
1 2
1 3
1 4

Output

Copy

A B B B

Input

Copy

10
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10

Output

Copy

D C B A D C B D C D

Note

In the first example, for any two officers of rank ‘B‘, an officer with rank ‘A‘ will be on the path between them. So it is a valid solution.

思路:

题目是给一个树,在树上的节点标号,要求是两个相同标号的连通的路径上必须有一个比他们等级高的标号。

刚开始时,这样想的:画了一幅图(很简单的),我把度数为一的标号为‘Z‘,删掉这些点,又出现了度数唯一的点,标为‘Y‘,再删掉,这样每次标记度数为一的点然后删到最后只剩两个点再特殊处理一下,如果这个过程中出现了字母用完的情况就说明不可能。但是这样做有个问题,其实字母用完了还是有可能继续完成标号的,我又改为字母用完了有倒序从‘B‘到‘Z‘标号,这样倒过来倒过去,还是错了,_(:з」∠)__

真正的做法是每次找树的重心,在重心处标号,根据重心定义(当前所有节点中最大的子树最小的节点),重心的最大子树的大小不会超过重心所在子树的一半。如果树退化成一条链,可以标记的节点数为\(1+2+4+...+2^{25}=2^{26}\)个节点,远远多于题目的限制。如果树不退化成链,那么可标记的点更多。因此必有解。

注意的是divide函数里面下一次divide是\(rt\)而不是\(v\)啊,血的教训啊w(?Д?)w,不是找的重心当然会把标记用光。

代码:

#include <iostream>
#include <algorithm>
#define INF 0x3f3f3f3f
#define max_n 200005
using namespace std;
int n;//n为节点数
char ans[max_n];
//链式前向星
int cnt = 0;
int head[max_n];
struct edge
{
    int v;
    int nxt;
}e[max_n<<1];
void add(int u,int v)
{
    ++cnt;
    e[cnt].v=v;
    e[cnt].nxt=head[u];
    head[u]=cnt;
}
int rt,ms;//rt为重心,ms是最小 最大子树的大小
int Size;//当前整棵树的大小
int sz[max_n];//sz[i]表示以i为根的子树大小
int mson[max_n];//mson[i]表示以i的最大子树的大小
bool visit[max_n];//标记是否分治过

//求重心函数
void get_root(int u,int from)
{
    sz[u]=1;mson[u]=0;//开始时以u为根的子树大小为1,u的最大子树为0
    for(int i=head[u];i;i=e[i].nxt)//遍历与u相连边
    {
        int v=e[i].v;
        if(visit[v]||v==from) continue;//防止重复遍历
        get_root(v,u);
        sz[u]+=sz[v];//更新以u为根的子树大小
        mson[u]=max(mson[u],sz[v]);//更新u的最大子树
    }
    if(Size-sz[u]>mson[u]) mson[u]=Size-sz[u];//看是否另一半子树更大
    if(ms>mson[u]) ms=mson[u],rt=u;//更新最小的最大子树和重心
}

//求解答案函数
//分函数
void divide(int u,int ssize,int ch)
{
    visit[u]=true;//当前节点已分治
    ans[u] = ch;
    for(int i = head[u];i;i=e[i].nxt)
    {
        int v=e[i].v;
        if(visit[v]) continue;//已分治过的不用再分治
        ms=INF;rt=0;//每一次求重心都要初始化这两个值
        Size=sz[v]<sz[u]?sz[v]:ssize-sz[u];
        get_root(v,0);//求出子树的重心
        divide(rt,Size,ch+1);//分治子树
    }
}
int main()
{
    cin >> n;
    for(int i = 1;i<n;i++)
    {
        int u,v;
        cin >> u >> v;
        add(u,v);
        add(v,u);
    }
    Size=n;//开始为n整棵树大小
    rt=0;ms=INF;
    get_root(1,0);
    /*for(int i = 1;i<=n;i++)
    {
        cout << "sz " << sz[i] << " mson " << mson[i] << endl;
    }
    cout << "rt " << rt << endl;*/
    divide(rt,n,0);
    for(int i = 1;i<=n;i++)
    {
        char chr = ans[i]+'A';
        cout << chr << " ";
    }
    cout << endl;
    return 0;
}

参考文章:

九野的博客,Codeforces 321C Ciel the Commander 树分治,https://blog.csdn.net/acmmmm/article/details/46931215

原文地址:https://www.cnblogs.com/zhanhonhao/p/11314994.html

时间: 2024-10-12 13:31:11

Codeforces G. Ciel the Commander的相关文章

CodeForces 321C Ciel the Commander

Ciel the Commander Time Limit: 1000ms Memory Limit: 262144KB This problem will be judged on CodeForces. Original ID: 321C64-bit integer IO format: %I64d      Java class name: (Any) Now Fox Ciel becomes a commander of Tree Land. Tree Land, like its na

Codeforces 321C Ciel the Commander 树分治裸题

题目链接 题意: 给定一棵树,要用字母A-Z 填到每个节点上 字母可以无限使用,但A至多只能用一次 目标:对于任意两个相同字母的节点,他们之间的路径上必须有至少一个节点的字母比他们小 例如:在两个C之间至少要有一个A 或者一个B 问: 输出填涂方案. 树分治即可,最多支持2^25个节点,不会无解. #include <iostream> #include <string> #include <vector> #include <cstring> #inclu

Codeforces 321E Ciel and Gondolas

传送门:http://codeforces.com/problemset/problem/321/E [题解] 首先有一个$O(n^2k)$的dp. # include <stdio.h> # include <string.h> # include <iostream> # include <algorithm> // # include <bits/stdc++.h> using namespace std; typedef long lon

codeforces 321E Ciel and Gondolas 四边形不等式

题目大意:给定n个人,需要分k次过河,两个人i,j如果同乘一条船就会产生ai,j的代价,求最终代价的最小值 这个玩应显然满足四边形不等式(虽然我并不知道这个不等式是啥 然后就是决策单调(虽然我并不知道为何满足四边形不等式一定决策单调 然后就能分治做辣... 定义Solve(l,r,optl,optr)表示当前在处理区间[l,r],最优决策区间为[optl,optr] 然后我们用区间[optl,min(optr,mid?1)]的f值来更新f[mid],并记录最优决策点pos 那么[l,mid?1]

CodeForces 321A Ciel and Robot(数学模拟)

题目链接:http://codeforces.com/problemset/problem/321/A 题意:在一个二维平面中,開始时在(0,0)点,目标点是(a.b),问能不能通过反复操作题目中的指令,从原点移动到目标点. 分析:如果一次完毕全部的命令后.移动到了(xx,yy),而且从(Xi.Yi)反复操作k次指令到达目标点.则能够列出方程 Xi + k * xx = a && Yi + k * yy = b.然后解出k.推断k是否大于等于0就可以. #include <cstdi

cf 321C - Ciel the Commander

题意:给一棵树,树上每个节点随便放置一个A-Z的字幕,A>B>C>....>Z,输出一种放置方案 使得任意两点之间的路径上有一个节点比两个节点的上的字母都大 分析:第二个样例是一个链,给了我灵感,只要找到中间的一个点,然后向两边递减就好了,然后点分治就好了 #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<vect

Codeforces 321B Ciel and Duel KM

题目链接 题意: 类似于游戏王的卡牌游戏,每个随从都有嘲讽... 输入n m 下面n行给出对手的随从当前状态和强壮值. 下面m行给出自己的随从的强壮值. 表示自己有m个随从,对手有n个随从.每个随从有一个强壮值. 现在是自己进攻的回合,自己的每个随从可以攻击一次(也可以不攻击) 若对手的随从都死光了,那么可以直接攻击玩家,造成与强壮值相等的伤害. 否则就要先攻击对手的随从. 对手的随从有防御状态(Defense) 和 攻击状态(Attack),每个随从也有一个强壮值. 1.若攻击对手的攻击状态随

Codeforces 321A Ciel and Robot 枚举答案

题目链接 枚举机器人走的最后一步,用终点坐差后计算周期次数 trick:周期次数要>=0 #include <iostream> #include <string> #include <vector> #include <cstring> #include <cstdio> #include <map> #include <queue> #include <algorithm> #include <

Codeforces 321B Ciel and Duel

题意:对方有N张卡牌,每一张卡牌要么是攻击模式要么是防守模式,你有M张卡牌,都是攻击模式 ,每张卡牌都有一个值,你可以进行一下的任意操 1)如果对方牌都被你消灭了,那么你任选一张没有选过的牌是对方遭受牌值的攻击. 2)可以选择一张没有选过值为X的牌,攻击对方一张攻击模式值为Y 的牌  对对方造成(X-Y)的伤害并把牌消灭 X必须 大于等于Y 3)可以选择一张没有选过值为X的牌,攻击对方一张防守模式值为Y 的牌  对对方不造成伤害,把对方牌消灭. X必须大于Y 解题思路:暴力 + DP? 解题代码