randomwalking(10.2hu测)

这里写图片描述

这里写图片描述

这里写图片描述

分析:
当时看到概率期望,光速弃疗
写了一个n^2暴力,30分稳

那我们就来看看正解:
son记录和该节点直接相连的结点个数
两遍dfs
第一遍从叶子向根转移
这里写图片描述

第二遍dfs稍微有点难理解
第二遍dfs处理以每个点为起点的概率(就是答案啦)
从根向叶子转移
f[1][0]=f[1][1]
这里写图片描述
这里写图片描述

//这里写代码片
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#define ll long long

using namespace std;

const int N=1000010;
const double INF=1e17;
const double eps=1e-8;
int n;
int a[N];
struct node{
    int x,y,nxt;
};
node way[N<<1];
int st[N],tot=0,ans,son[N];
double ansx,f[N][2];

int dcmp(double x)
{
    if (fabs(x)<eps) return 0;
    else if (x>0) return 1;
    else return -1;
}

void add(int u,int w)
{
    tot++;
    way[tot].x=u;way[tot].y=w;way[tot].nxt=st[u];st[u]=tot;
    tot++;
    way[tot].x=w;way[tot].y=u;way[tot].nxt=st[w];st[w]=tot;
}

void dfs_1(int now,int fa)
{
    for (int i=st[now];i;i=way[i].nxt)
        if (way[i].y!=fa)
            son[now]++;
    if (fa!=0) son[now]++;
    for (int i=st[now];i;i=way[i].nxt)
        if (way[i].y!=fa)
        {
            dfs_1(way[i].y,now);
            if (fa!=0)
               f[now][0]+=f[way[i].y][0]/(double)(son[now]-1);
            else f[now][0]+=f[way[i].y][0]/(double)son[now];
        }
    f[now][0]+=a[now];
}

void dfs_2(int now,int fa)
{
    if (now==1) f[now][1]=f[now][0];
    else
    {
        double temp1=(f[fa][1]-a[fa])*son[fa];
        double temp2=temp1-f[now][0];
        double temp3=(f[now][0]-a[now])*(son[now]-1);
        if (son[fa]>1)
            f[now][1]=(temp2/(double)(son[fa]-1)+a[fa])/(double)son[now]+temp3/(double)son[now];
        else 
            f[now][1]=a[fa]/(double)son[now]+temp3/(double)son[now];
        f[now][1]+=a[now];
    }
    for (int i=st[now];i;i=way[i].nxt)
        if (way[i].y!=fa)
            dfs_2(way[i].y,now);
}

int main()
{
    freopen("walking.in","r",stdin);  
    freopen("walking.out","w",stdout);
    scanf("%d",&n);
    for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    for (int i=1;i<n;i++)
    {
        int u,w;
        scanf("%d%d",&u,&w);
        add(u,w);
    }
    if (n==1) {
        printf("1
");
        return 0;
    }
    ansx=INF;
    dfs_1(1,0);
    dfs_2(1,0);
    for (int i=1;i<=n;i++)
        if (f[i][1]<ansx)
           ansx=f[i][1],ans=i;
    printf("%d
",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/wutongtong3117/p/7673102.html