牛オフの練習試合55 E-ツリーツリーDP

問題の意味

あなたはの大き持っています\(N \)ポイントから、ツリーを\(1 \)\(N \)ラベル。
セット\(dis⁡(x、y)は 、\) を表し\(X \)\(Y \)距離。
探している\(\ sum_ {I = 1 } ^ {N} \ sum_ {J = 1} ^ {n}はDIS ^ 2(I、J)\) に(998244353 \)\モジュロの結果を。

分析

セット\(D_X \)ポイントです\(X \)の深さ。

\(DIS(X、Y)= D_X + d_y-2 * LCA(X、Y)\)

\(DIS ^ 2(X、Y)= D_X ^ 2 + d_y ^ 2 + 2 * D_X * d_y-4 * D_ {LCA(X、Y)} *(D_X + d_y)+ 4 * D_ {LCA(X 、Y)} ^ 2 \)

Dpが精力的にツリーは離れて取得します。

コード

#include<bits/stdc++.h>
#define fi first
#define se second
#define lson l,mid,p<<1
#define rson mid+1,r,p<<1|1
#define pb push_back
#define ll long long
using namespace std;
const int inf=1e9;
const int mod=998244353;
const int maxn=1e6+10;
int n;
ll sz[maxn],d[maxn],dep[maxn];
vector<int>g[maxn];
ll ans;
void dfs(int u,int fa){
    sz[u]=1;d[u]=d[fa]+1;
    dep[u]=d[u];
    for(int x:g[u]){
        if(x==fa) continue;
        dfs(x,u);
        sz[u]=(sz[u]+sz[x])%mod;
        dep[u]=(dep[u]+dep[x])%mod;
    }
    for(int x:g[u]){
        if(x==fa) continue;
        ans=(ans+sz[x]*(sz[u]-sz[x])%mod*4%mod*d[u]%mod*d[u]%mod)%mod;
        ans=(ans+4*d[u]%mod*d[u]%mod*sz[x]%mod)%mod;
        ans=(ans-dep[x]*(sz[u]-sz[x])%mod*8%mod*d[u]%mod)%mod;
        ans=(ans-d[u]*sz[x]%mod*8%mod*d[u]%mod)%mod;
    }
}
int main(){
    //ios::sync_with_stdio(false);
    //freopen("in","r",stdin);
    scanf("%d",&n);
    for(int i=1,x,y;i<n;i++){
        scanf("%d%d",&x,&y);
        g[x].pb(y);g[y].pb(x);
    }
    dfs(1,0);
    for(int i=1;i<=n;i++){
        ans=(ans+d[i]*d[i]%mod*2%mod*(n-1)%mod)%mod;
        ans=(ans+d[i]*(dep[1]-d[i])%mod*2%mod)%mod;
    }
    ans=(ans+mod)%mod;
    printf("%lld\n",ans);
    return 0;
}

おすすめ

転載: www.cnblogs.com/xyq0220/p/12044611.html