BZOJ 5463: [APIO2018] Duathlon round side tree Tree + DP

title

BZOJ 5463
LUOGU 4630
Description

Bits town road network connected by two-way road n m intersections composition.
Recently, the town won the right to host a bit Duathlon Championships. There are two game schedule: the first player to complete a period of long-distance race, and then complete the second stage cycling race.
To match the route planning as follows:
1, first select three mutually different junction twenty-two s, c and F, respectively, as the starting point of the game, the switching point (marathon athletes after reaching that point, to the end of cycling) ,end.
2, selected from a s, c through f of the final path. For safety reasons, the path chosen through the same point at most once.
Before the planned path, the mayor would like to invite you to help calculate the total number of different selection s, c and f of the program, so that the step 2 can at least design a path to meet the requirements.

Input

The first line contains two integers n and m, respectively represent the number of intersections and a two-way road.
Next m lines of two integers v_i, u_i. It indicates the presence of a bidirectional connection path intersections v_i, u_i (1 <= v_i , u_i <= n, v_i! = U_i).
To ensure that between any two intersections, up to a two-way road is directly connected.
n <= 1e5, m <= 2e5

Output

Number of program line of output contains an integer representing meet the requirements of different selection s, c and f

Sample Input

4 3
1 2
2 3
3 4

Sample Output

8

Source

Acknowledgments Qingyu upload

analysis

The tree is round side, each point of FIG connected components to build a double-side point, the point where all communication components connected to this side of the point, a tree is formed, the original point dots.
Round side trees can handle many of the problems associated with the connectivity graph.

Ah, concept finished, return to this issue below (a topic meaning):

For all ordered points \ ((X, Y), X = \ Not Y \) , \ (\ SUM _ {(X, Y)} \) may appear in the \ (X \) to \ (Y \) number of points on a simple path, excluding the \ (X \) and \ (Y \) .

With different situations may occur in \ (X \) to \ (Y \) of points on a simple path (not including \ (X \) and \ (Y \) ):

  1. \ (X \) and \ (Y \) at the same point of the double: double the size of the point where the Save \ (2 \) .
  2. \ (X \) and \ (Y \) is not cut at the same point bis point: \ (X \) to \ (Y \) in the path (not including \ (X \) and \ (Y \) ) and double the size of the point (Note: in addition to \ (x \) and \ (y \) cut point outside only be counted once).
  3. \ (X \) and \ (Y \) is not the same and neither is it double cut point: \ (X \) to \ (Y \) all points on the path of double size minus the sum of the point-bis (path number plus one).
    ...

In conclusion, we set the value of the right side of the point corresponding point double size, of a weight of the dot \ (- 1 \) , it may occur in \ (X \) to \ (Y \) on a simple path points (not including \ (X \) and \ (Y \) ) is a round square tree \ (X \) to \ (Y \) the right point on the path and the value.
So, we have problem into a tree and ordered all the dots to both the Two Ways and the sum of the weights.

  • Status:
    \ (F [X] \) represents \ (X \) path weight within the subtree of the disorder and the sum of dots.
    \ (g [x] \) represents \ (X \) to \ (X \) path weight of all the dots in the sub-tree and the sum.
    \ (sum [x] \) represents \ (X \) the number of dots in the sub-tree.
    \ (val [x] \) represents \ (X \) weights point.
  • Transfer:
    \ (SUM [X] = [X is dot] + \ sum_ {Y \ in Son [X]} SUM [Y] \)
    \ (G [X] = \ sum_ {Y \ in Son [X] } \ {g [y] +
    sum [y] \ times val [x] \} \) in the enumeration subtree \ (Y \) in process of recording \ (g [x] \) and \ (SUM [ X] \) represents \ (Y \) subtree before (not including the \ (Y \) ) of \ (DP \) values: \ (F [X] + = F [Y] + G [X] × SUM [y] + g [y] × sum [x] \)

Note that FIG communication may not, so the answer is: \ (2 \ Times \ sum_ {I is the root of a communication block F} [I] \) .
Overall complexity \ (O (n-m +) \) .

Reference: xyz32768 .

code

#include<bits/stdc++.h>
using namespace std;
const int maxn=4e5+10;

char buf[1<<15],*fs,*ft;
inline char getc() { return (ft==fs&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),ft==fs))?0:*fs++; }
template<typename T>inline void read(T &x)
{
    x=0;
    T f=1, ch=getchar();
    while (!isdigit(ch) && ch^'-') ch=getchar();
    if (ch=='-') f=-1, ch=getchar();
    while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
    x*=f;
}

template<typename T>inline void write(T x)
{
    if (!x) { putchar('0'); return ; }
    if (x<0) putchar('-'), x=-x;
    T num=0, ch[20];
    while (x) ch[++num]=x%10+48, x/=10;
    while (num) putchar(ch[num--]);
}

struct Graph
{
    int ver[maxn<<1],Next[maxn<<1],head[maxn],len;
    Graph()
    {
        memset(head,0,sizeof(head));
        len=0;
    }

    inline void add(int x,int y)
    {
        ver[++len]=y,Next[len]=head[x],head[x]=len;
        ver[++len]=x,Next[len]=head[y],head[y]=len;
    }
} G1,G2;

int dfn[maxn],low[maxn],id;
int Stack[maxn],top;
int val[maxn],belong[maxn],siz[maxn],tot;
inline void tarjan(int x)
{
    dfn[x]=low[x]=++id;
    Stack[++top]=x;
    for (int i=G1.head[x]; i; i=G1.Next[i])
    {
        int y=G1.ver[i];
        if (!dfn[y])
        {
            tarjan(y);
            low[x]=min(low[x],low[y]);
            if (low[y]>=dfn[x])
            {
                int k;
                ++tot;
                do
                {
                    k=Stack[top--];
                    ++siz[tot];
                    G2.add(tot,k);
                } while (k!=y);
                ++siz[tot];
                G2.add(tot,x);
            }
        }
        else low[x]=min(low[x],dfn[y]);
    }
}

int n,m,sum[maxn];
long long ans,f[maxn],g[maxn];
inline void dfs(int x,int fa)
{
    sum[x]=(x<=n);
    g[x]=x<=n?-1:0;
    for (int i=G2.head[x]; i; i=G2.Next[i])
    {
        int y=G2.ver[i];
        if (y==fa) continue;
        dfs(y,x);
        f[x]+=f[y]+g[x]*sum[y]+g[y]*sum[x];//f[x] 表示 x 的子树内无序圆点对的路径权值和之和。
        g[x]+=g[y]+1ll*siz[x]*sum[y];//g[x]表示 x 到 x 的子树内所有圆点的路径权值和之和。
        sum[x]+=sum[y];//sum[x]表示 x 的子树内圆点的个数。
    }
}

int main()
{
    read(n);read(m);tot=n;
    memset(siz,-1,(n+1)<<2);
    for (int i=1,x,y; i<=m; ++i) read(x),read(y),G1.add(x,y);
    for (int i=1; i<=n; ++i)
        if (!dfn[i]) tarjan(i),dfs(i,0),ans+=f[i]<<1;
    write(ans),puts("");
    return 0;
}

Guess you like

Origin www.cnblogs.com/G-hsm/p/11323260.html