CF 321C Ciel the Commander(树的点分治)

题目链接:http://codeforces.com/problemset/problem/321/C

题意:给出一棵树,为每个节点分配一个大写字母A到Z。满足对于任意两个字母相同的节点u和v,uv的路径上至少存在一个节点的字母是大于uv的字母的(A最大)。

思路:每次找到当前树的重心,将其分成若干个子树继续进行DFS。总深度大于26则无解。否则每个树的字母为其深度。

 




vector<int> g[N],V1,V2;
int size[N],visit[N];
int n;


void DFS(int u,int pre)
{
    size[u]=1;
    int i,v,son=0;
    FOR0(i,SZ(g[u]))
    {
        v=g[u][i];
        if(visit[v]||v==pre) continue;
        DFS(v,u);
        size[u]+=size[v];
        if(size[v]>son) son=size[v];
    }
    V1.pb(son); V2.pb(u);
}


int getRoot(int u)
{
    V1.clear(); V2.clear();
    DFS(u,-1);
    int tot=SZ(V1);
    int i,Min=INF,temp,ans;
    FOR0(i,SZ(V1))
    {
        temp=max(V1[i],tot-V1[i]);
        if(temp<Min) Min=temp,ans=V2[i];
    }
    return ans;
}


int dep[N],MaxDep;




void solve(int u,int d)
{
    u=getRoot(u); MaxDep=max(MaxDep,d);
    dep[u]=d;
    visit[u]=1;
    int i,v;
    FOR0(i,SZ(g[u]))
    {
        v=g[u][i];
        if(visit[v]) continue;
        solve(v,d+1);
    }
}


int main()
{
    RD(n);
    int i,x,y;
    FOR1(i,n-1)
    {
        RD(x,y);
        g[x].pb(y);
        g[y].pb(x);
    }
    solve(1,0);
    if(MaxDep>=26)
    {
        puts("Impossible!");
        return 0;
    }
    printf("%c",dep[1]+'A');
    for(i=2;i<=n;i++) printf(" %c",dep[i]+'A');
    puts("");
    return 0;
}

你可能感兴趣的:(command)