nowcoder Wannafly挑战赛1 A 题 【树形dp or 点分治】

传送门
//题意不多说.
//说下思路: 这道题最最简单的做法就是On的扫一遍, 然后根据奇偶的点直接算答案, 然后最近才学了点分治, 又因为这道题就是维护树上的路径问题, 所以想练练手, 于是我就用的点分治做的, 虽然是牛刀…..

然后一样的路径分为过根节点的和不过的, 我们还是只讨论过根节点的, 其他的递归处理即可. 然后依然根据奇偶来, (还是一样的, xixi), 然后注意一样的要处理子树的情况. 套一套板子即可.

AC Code

const int maxn = 1e5+5;
int n, cnt, head[maxn], k, vis[maxn], root, maxx, dis[maxn];
int num, tot, siz[maxn], mv[maxn];
struct node {
    int to, w, next;
} e[maxn<<1];

void add(int u, int v, int w)
{
    e[cnt] = (node){v,w,head[u]};
    head[u] = cnt++;
}

void getroot(int u, int fa)
{
    siz[u] = 1, mv[u] = 0;
    for (int i = head[u]; ~i; i = e[i].next) {
        int to = e[i].to;
        if (to == fa || vis[to]) continue;
        getroot(to, u);
        siz[u] += siz[to];
        mv[u] = max(mv[u], siz[to]);
    }
    mv[u] = max(mv[u], tot - siz[u]);
    if (mv[u] < mv[root]) root = u;
}

void getdis(int u,int fa,int dep)
{
    dis[++num] = dep;
    for (int i = head[u]; ~i; i = e[i].next) {
        int to = e[i].to;
        if (to == fa || vis[to]) continue;
        getdis(to, u, dep + e[i].w);
    }
}
ll ans;
ll cal(int u,int f)
{
    num = 0;
    getdis(u,-1,f);
    sort(dis+1,dis+num+1);
    int r = num ;
    ll cnt1=-1,cnt2=-1;
    for(int l = 1; l <= r; l++) {
        if(dis[l]%2) cnt1++;
        else cnt2++;
    }
    return (cnt1+1)*cnt1/2 + (cnt2+1)*cnt2/2;
    //这个就是计算的公式.(注意根节点以及奇数数个数的影响,所以初值为-1).
}

void work(int u)
{
    vis[u] = 1;
    ans += cal(u, 0);
    for (int i = head[u]; ~i; i = e[i].next) {
        int to = e[i].to;
        if (vis[to]) continue;
        ll tmp = cal(to, e[i].w);
        ans -= tmp;
        mv[root=0] = tot = siz[to];
        getroot(to, -1);
        work(root);
    }
}

void solve()
{
    while(~scanf("%d",&n)){
        cnt = 0 ; Fill(head,-1); Fill(vis,0);
        for (int i = 1; i < n; i++) {
            int u, v;
            scanf("%d%d",&u,&v);
            add(u, v, 1); add(v, u, 1);
        }
        ans = 0;
        mv[root=0] = tot = n;
        getroot(1, -1);
        work(root);
        cout << ans << endl;
    }
}

你可能感兴趣的:(树的点分治)