2018-team4-modules-点分治

从 Trac 迁移的文章

这是从旧校内 Wiki 迁移的文章,可能存在一些样式问题,您可以向 memset0 反馈。

原文章内容如下:

{{{
// 点分治求树上路径边权和为3的倍数的路径的数目
struct Edge{
    int to,next,dis;
}G[maxn<<1];
int head[maxn],cnt;
void add(int u,int v,int d){
    G[++cnt].to = v;
    G[cnt].next = head[u];
    G[cnt].dis = d;
    head[u] = cnt;
}
bool vis[maxn];
int dis[maxn],root,f[maxn];
int size,siz[maxn];
#define v G[i].to
void dfs1(int u,int fa){
    siz[u] = 1;f[u] = 0;
    for(int i = head[u];i;i=G[i].next){
        if(v == fa || vis[v]) continue;
        dfs1(v,u);
        siz[u] += siz[v];
        f[u] = max(f[u],siz[v]);
    }
    f[u] = max(size - siz[u],f[u]);
    if(f[u] < f[root]) root = u;
}
int num[5];
void dfs2(int u,int fa){
    ++num[dis[u]];siz[u] = 1;
    for(int i = head[u];i;i=G[i].next){
        if(v == fa || vis[v]) continue;
        dis[v] = dis[u] + G[i].dis;
        dis[v] %= 3;
        dfs2(v,u);
        siz[u] += siz[v];
    }return;
}
int calc(int u,int k){
    num[0] = num[1] = num[2] = 0;
    dis[u] = k % 3;
    dfs2(u,0);
    return num[1]*num[2]*2 + num[0]*num[0];
}
int ans = 0;
void dfs(int u){
    ans += calc(u,0);
    vis[u] = true;
    for(int i = head[u];i;i=G[i].next){
        if(vis[v]) continue;
        ans -= calc(v,G[i].dis);
        size = siz[v];root = 0;
        dfs1(v,0);
        dfs(root);
    }
}
#undef v
int main(){
    int n;read(n);
    for(int i=1,u,v,d;i<n;++i){
        read(u);read(v);read(d);
        add(u,v,d);add(v,u,d);
    }
    size = f[0] = n;
    dfs1(1,0);
    dfs(root);
    return 0;
}
}}}
// 点分治求树上路径边权和为3的倍数的路径的数目
struct Edge{
    int to,next,dis;
}G[maxn<<1];
int head[maxn],cnt;
void add(int u,int v,int d){
    G[++cnt].to = v;
    G[cnt].next = head[u];
    G[cnt].dis = d;
    head[u] = cnt;
}
bool vis[maxn];
int dis[maxn],root,f[maxn];
int size,siz[maxn];
#define v G[i].to
void dfs1(int u,int fa){
    siz[u] = 1;f[u] = 0;
    for(int i = head[u];i;i=G[i].next){
        if(v == fa || vis[v]) continue;
        dfs1(v,u);
        siz[u] += siz[v];
        f[u] = max(f[u],siz[v]);
    }
    f[u] = max(size - siz[u],f[u]);
    if(f[u] < f[root]) root = u;
}
int num[5];
void dfs2(int u,int fa){
    ++num[dis[u]];siz[u] = 1;
    for(int i = head[u];i;i=G[i].next){
        if(v == fa || vis[v]) continue;
        dis[v] = dis[u] + G[i].dis;
        dis[v] %= 3;
        dfs2(v,u);
        siz[u] += siz[v];
    }return;
}
int calc(int u,int k){
    num[0] = num[1] = num[2] = 0;
    dis[u] = k % 3;
    dfs2(u,0);
    return num[1]*num[2]*2 + num[0]*num[0];
}
int ans = 0;
void dfs(int u){
    ans += calc(u,0);
    vis[u] = true;
    for(int i = head[u];i;i=G[i].next){
        if(vis[v]) continue;
        ans -= calc(v,G[i].dis);
        size = siz[v];root = 0;
        dfs1(v,0);
        dfs(root);
    }
}
#undef v
int main(){
    int n;read(n);
    for(int i=1,u,v,d;i<n;++i){
        read(u);read(v);read(d);
        add(u,v,d);add(v,u,d);
    }
    size = f[0] = n;
    dfs1(1,0);
    dfs(root);
    return 0;
}