【算法练习】CodeForces1007F Dominant Indices (树上启发合并)

题意

求每个点的子树中哪一层节点数最多,如果有节点数最多不唯一,取层数最小的。

题解

树上启发合并。开个数组记录当前深度的节点数目,每次更新时保存答案,注意求得是对于子树的深度,所以最后要减去递归时节点的深度。
复杂度 O ( n l o g n )
这道题是被题意卡了,完全不知道题面再说什么。。

代码

#include<bits/stdc++.h>
using namespace std;
typedef double db;
typedef long long ll;
typedef unsigned long long ull;
const int nmax = 1e6+7;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
const ull p = 67;
const ull MOD = 1610612741;
int head[nmax],deep[nmax],sz[nmax],son[nmax],tot,ans[nmax],cnt[nmax],mxval,nowans;
bool visit[nmax];
struct node{int to,nxt;}e[nmax<<1];
void add_edge(int u, int v){e[tot].to = v, e[tot].nxt = head[u], head[u] = tot++;}
void dfs1(int u, int f, int d){
    deep[u] = d, sz[u] = 1;
    for(int i = head[u];i!=-1;i = e[i].nxt){
        int v = e[i].to;
        if(v != f) {
            dfs1(v,u,d+1), sz[u] += sz[v];
            if(sz[son[u]] < sz[v]) son[u] = v;
        }
    }
}
void update(int u, int f, int tag){
    cnt[deep[u]] += tag;
    if(tag == 1 && cnt[deep[u]] >= mxval){
        if(cnt[deep[u]] > mxval) mxval = cnt[deep[u]], nowans = deep[u];
        else if(cnt[deep[u]] == mxval && deep[u] < nowans) nowans = deep[u];
    }
    for(int i = head[u];i!=-1;i=e[i].nxt){
        int v = e[i].to;
        if(v!=f && !visit[v]) update(v,u,tag);
    }
}
void dfs2(int u, int f, bool keep = false){
    for(int i = head[u];i!=-1;i=e[i].nxt){
        int v = e[i].to;
        if(v != f && v != son[u]) dfs2(v,u);
    }
    if(son[u]) dfs2(son[u],u,true), visit[son[u]] = true;
    update(u,f,1);
    ans[u] = nowans - deep[u];
    if(son[u]) visit[son[u]] = false;
    if(!keep) update(u,f,-1),mxval = nowans = 0;
}
int n;
int main() {
    memset(head,-1,sizeof head);
    scanf("%d",&n);
    int u, v;
    for(int i = 1;i<n;++i){
        scanf("%d %d",&u,&v);
        add_edge(u,v),add_edge(v,u);
    }
    dfs1(1,-1,1);
    dfs2(1,-1);
    for(int i = 1;i<=n;++i) printf("%d\n",ans[i]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/pengwill97/article/details/81475264