[14/11/19] heteroaryl title | within the block operation

Questions surface:

Untitled

Analysis: Since it is desirable to seek the total number of programs for \ (the n-^ 2 \) , but also to find out the expectations of multiplying a \ (the n-^ 2 \) , the title is intended to be simplified to \ (\ sum_i ^ n \ sum_j NW ^ [I] [J] \) , wherein the definition of \ (w [i] [j ] \) represents the connection (i, j \) \ black evil Unique number occurring in the chain before, redefinition \ (d (i, j) \) represents a linking \ (i, j \) in the chain.

   To simplify the problem, we believe that this photo shows a tree(Originally), To find any point of the root, but the evil forces believed to be the edge of each color. So obvious, to meet the tree each node has one and only one parent edge(nonsense)And each side will have a single color rather than a colorful (By $ $ \ (XZY \) giant guy so not nonsense), i.e., each point corresponding to a unique color, it may be assumed that each point of the parent color edge color.

   According to this property, we can soon have a preliminary idea of ​​inclusion and exclusion. Consider such a picture.

S

   For the entire operation difficult determination we FIG contribution, but if we are in a fixed color \ (A \) , the edge of this color are all turned off, then the tree becomes a plurality of blocks are not in communication , while all of the colors for each block in the block, as \ (a \) edges are not contribute. In other words, for this block, the color \ (A \) does not contribute.

S - copy

   即上图,对于每个绿色的块 \(S\) 内,\(中出现了红色边\sum^{S.card}_i \sum^{S.card}_j [d(i,j)中出现了红色边]=0\)

   (从这行以下请感性理解或自觉 \(Mod\) \(XZY\) \(or\) \(LX\) \(or\) \(HL\) \(or\) \(CXR\) \(or\) \(LWY\)。)

\(Sol\):我们实际上只需要统计这个颜色 \(A\) 在整棵树里可能带来的所有影响(即 \(n^2\) ,它至多存在于 \(n^2\) 条链中),减去各个块内的链数(即 \(S.card^2\) ,它在这个块里的所有链上都没有贡献),就是这种颜色所带来的总的贡献。

   考虑怎么求这个贡献。

   由于我们已经知道了每个点对应且仅对应一种颜色,即上文说过的这个点父边的颜色,那么我们就可以暴力 \(dfs\) 。对于当前这个节点 \(i\) 所对应的颜色 \(col[i]\) 操作即可。

   维护一个 \(top[i]\) 表示这个节点 \(i\) 所对应的颜色 \(col[i]\)\(dfs\) 的过程中上一次出现的位置。如上图,\(top[2]=1\)\(top[3]=1\)\(top[4]=2\) ;特别的,如果这个颜色是第一次出现,那么它的 \(top[i]\) 将会被设为 \(0\) 。如上图,\(top[1]=0\)\(top[5]=0\)

   在这种时候就需要一个 \(lst\) 辅助数组滚动记录,不过这不是重点。

   接下来就是求这些连通块内的大小。显而易见的,每个以 \(i\) 为深度最小的节点的连通块大小就是 \(f[i]=size[top[i]]-\sum _{j \in \{x|top[x]=i\}}size[j]\) ,其中 \(size[u]\) 表示 \(u\) 的子树大小 。通俗一点的解释就是下图。

S - copy (2)

   我把绿的改成紫的了,仅此而已。

   但是这就很容易能得到:每个以 \(i\) 为最小深度的连通块的大小,就是这个 \(i\) 的子树大小,减掉所有以它为端点的向下延伸的链中,第一次碰到的相同颜色的节点的子树大小。注意,是对于每条链而言的第一次碰到的相同颜色。如上图,节点 \(2\) 所对应的连通块大小就是 \(size[2]-size[4]\) ,因为节点 \(4\)\(2\) 的子树中,且与 \(2\) 的颜色相同,且是 \(d(2,4)\) 上除 \(2\) 外第一个同为红色的点;节点 \(3\) 所对应的连通块大小就是 \(size[3]\) ,因为它是一个叶子节点。

   很明显,\(ans=\sum_i^n (n^2-f[i]^2-rtc[i])=n^3-\sum_i^n (f[i]^2+rtc[i])\) ,意义就是每种颜色(共 \(n\) 种,所以是 \(n*n^2=n^3\))的贡献除去这种颜色的无用贡献(本来应该对于每种颜色单独计算,但发现答案不互斥,直接求和),至于 \(rtc[i]\) 将在下面提到。

   Some pay attention to small details. First, if one does not open a new \ (F [I] \) , but directly modify \ (size [I] \) , Yaoan \ (DFS \) sequence addition and subtraction operations subtree, the tree can not be the direct (such as \ (std \) ). Since there may be things first child node minus minus parent.

   This data is then returned with a layer of restrictions (or subject forgot to say?), That is, \ (dfs \) sequence is \ ([1, n] \ ) of the order . This has led to what may play less demand \ (dfs \) loop sequence.

   Finally, the issue of each color in the whole tree in the first time, we need to use a \ (rtc [i] \) is stored, is initialized to \ (the n-\) , each search to \ (col [j ] = n-\) \ (\ & \) ! \ (Top [J] \) nodes \ (J \) requires \ (RTC [I] - = size [J] \) . Think about why.

   Then \ (A \) a.

\(Code\)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=500035;
const int maxm=1000035;
struct Edge
{
    int v,w;
    Edge(int a=0,int b=0):v(a),w(b) {}
}edges[maxm];
int n;
int size[maxn],rtc[maxn],top[maxn],lst[maxn];
int edgeTot,head[maxn],nxt[maxm];
ll ans;
int read(){
    char ch=getchar();
    int num=0,fl=1;
    for(;!isdigit(ch);ch=getchar())if(ch=='-') fl=-1;
    for(;isdigit(ch);ch=getchar())num=(num<<1)+(num<<3)+ch-48;
    return num*fl;
}
void addedge(int u,int v,int w)
{
    edges[++edgeTot]=Edge(v,w),nxt[edgeTot]=head[u],head[u]=edgeTot;
    edges[++edgeTot]=Edge(u,w),nxt[edgeTot]=head[v],head[v]=edgeTot;
}
void dfs(int x,int fa)
{
    size[x]=1;
    for(int i=head[x];i!=-1;i=nxt[i])
    {
        int v=edges[i].v,w=edges[i].w;
        if(v==fa) continue;
        top[v]=lst[w],lst[w]=v;
        dfs(v,x),size[x] += size[v];
        lst[w]=top[v];//,size[top[v]] -= size[v];
        if(!top[v]) rtc[w] -= size[v];
    }
}
int main()
{
//  freopen("forest.in","r",stdin);
//  freopen("forest.out","w",stdout);
    memset(head,-1,sizeof head);
    n=read();
    for(int i=1,u,v,w;i<n;i++)
    u=read(),v=read(),w=read(),addedge(u,v,w);
    for(int i=1;i<=n;i++)rtc[i]=n;
    ans=1ll*n*n*n;
    dfs(1,0);
    for(int i=1;i<=n;i++)
    if(top[i])size[top[i]]-=size[i];
    for(int i=1;i<=n;i++)
    {
        if(i!=1)ans-=1ll*size[i]*size[i];
        ans-=1ll*rtc[i]*rtc[i];
    }
    printf("%lld\n",ans);
    return 0;
}

Guess you like

Origin www.cnblogs.com/alexiswithlucifer/p/11863758.html