[Treasure] Problem solution (5-school joint examination 3day1)

analyze

If you hit the explosive search, you can get 60 points.
First of all, we know that the expectation can be accumulated, that is, the expectation of i going to k through j is equal to the expectation of i going to j plus the expectation of j going to k.
So let d[i] denote the out-degree of i, F[i] denote the expectation from i to the father of i, G[i] denote the expectation from the father of i to i, j denote any one of the sons of i, and k denote i The father of , l represents any one of the sons of k, and e represents the father of k.
It is easy to deduce:
\[F[i]=\dfrac{1}{d[i]}+\dfrac{1}{d[i]}\sum(1+F[j]+F[i])\ ]
\[G[i]=\dfrac{1}{d[k]}+\dfrac{1}{d[k]}(1+G[k]+G[i])+\dfrac{1} {d[k]}\sum(1+F[l]+G[i])\]
Simplified to get
\[F[i]=\sum{F[j]}+d[i]\]
\[ G[i]=G[k]+\sum{F[l]}+d[k]\]
and then walk in q times, it is easy to calculate the expectation from vi to vi+1 by multiplying lca, and you can accumulate the expectation. .

#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
int d[600000],g[600000],f[600000],last[600000],next[600000],a[600000],dad[60000][50],deep[600000],fsum[600000],gsum[600000],m2[100];
int n,m,test,q,p,tot;
int bj(int x,int y)
{
    next[++tot]=last[x];
    last[x]=tot;
    a[tot]=y;
    d[x]++;
}
int dg(int x,int fa)
{
    deep[x]=deep[fa]+1;
    f[x]+=d[x];
    for(int i=last[x];i;i=next[i])
    {
        if(a[i]!=fa)
        {
            dg(a[i],x);
            f[x]+=f[a[i]];
        }
    }
}
int dg1(int x,int fa)
{
    int allj=0;
    for(int i=last[x];i;i=next[i])
    {
        if(a[i]!=fa)
        {
            allj+=f[a[i]];
        }
    }
    for(int i=last[x];i;i=next[i])
    {
        if(a[i]!=fa)
        {
            g[a[i]]=d[x]+g[x]+allj-f[a[i]];
        }
    }
    for(int i=last[x];i;i=next[i])
    {
        if(a[i]!=fa)
        {
            dg1(a[i],x);
        }
    }
}
int dg2(int x,int fa)
{
    dad[x][0]=fa;
    fsum[x]=fsum[fa]+f[x];
    gsum[x]=gsum[fa]+g[x];
    for(int i=last[x];i;i=next[i])
    {
        if(a[i]!=fa)
            dg2(a[i],x);
    }
}
int work(int x,int y,int z)
{
    return fsum[x]-fsum[z]+gsum[y]-gsum[z];
}
int lca(int x,int y)
{
    if(x==y) return 0;
    int l=0;
    if(deep[x]<deep[y])
    {
        l=x;
        x=y;
        y=l;
        l=10000000;
    }
    int i,xx=x,yy=y,j;
    if(deep[xx]>deep[yy])
    {
        j=int(log2(deep[xx]));
        for(i=j;i>=0;i--)
        {
            if(deep[dad[xx][i]]>deep[yy])
            {
                xx=dad[xx][i];
            }
        }
        xx=dad[xx][0];
    }
    if(xx==yy)
    {
        if(l==0) return work(x,y,xx);
        else return work(y,x,xx);
    }
    j=int(log2(deep[xx]));
    for(i=j;i>=0;i--)
    {
        if (dad[xx][i]!=dad[yy][i])
        {
            xx=dad[xx][i];
            yy=dad[yy][i];
        }
    }
    xx=dad[xx][0];
    if(l==0) return work(x,y,xx);
        else return work(y,x,xx);
}
int main()
{
    int i,j,k,l,x,y;
    m2[0]=1;
    for(i=1;i<=20;i++)
        m2[i]=m2[i-1]*2;
    scanf("%d",&test);
    while(test--)
    {   
        scanf("%d",&n);
        tot=0;
        memset(d,0,sizeof(d));
        memset(g,0,sizeof(g));
        memset(f,0,sizeof(f));
        memset(a,0,sizeof(a));
        memset(last,0,sizeof(last));
        memset(next,0,sizeof(next));
        memset(dad,0,sizeof(dad));
        memset(deep,0,sizeof(deep));
        memset(fsum,0,sizeof(fsum));
        memset(gsum,0,sizeof(gsum));
        for(i=1;i<=n-1;i++)
        {
            scanf("%d%d",&x,&y);
            bj(x,y);
            bj(y,x);
        }
        deep[0]=0;
        dg(0,0);
        dg1(0,0);
        dg2(0,0);
        for(j=1;j<=int(log2(n));j++)
        {
            for(i=1;i<=n;i++)
            {
                dad[i][j]=dad[dad[i][j-1]][j-1];
            }
        }
        scanf("%d",&q);
        for(i=1;i<=q;i++)
        {
            int ans=0;
            scanf("%d%d",&p,&x);
            for(j=1;j<=p;j++)
            {
                scanf("%d",&y);
                ans+=lca(x,y);
                x=y;
            }
            printf("%d.0000\n",ans);
        }
        cout<<endl;
    }
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325847272&siteId=291194637