Topcoder SRM 561 DIV2 1000 FoxAndTouristFamilies

由于是树,所以两点之间只有一条路径,那么只要把每一条边砍断,再根据左右节点计算一下就好了

具体计算方法:假设这条砍掉的边就是full路,那么可以得到一个简单的性质,从这条路的左边到右边或者从右边到左右都一定会经过这条路,每一个点到除了自己以外其他点的概率就是p=1/(n-1).那么就可以转化为ans+=(当前情况的概率)*1.0也就是一条full路,到时候枚举边就可以得到总期望值了。期望值到底怎么算呢?如果从左到右来看,可以把左边所有家庭压缩到一个点,然后

P>=(p)()

右到左同理

P>=(p)()

然后ans+= P> * P>

#define M 55

class FoxAndTouristFamilies {
public:
    int cnt[M],dp[M],size[M];
    vector<int>st[M];
    bool mark[M][M];
    void dfs(int x,int pre){
        int &nw1=dp[x];
        int &nw2=size[x];
        nw1=cnt[x];
        nw2=1;
        for(int i=0;i<st[x].size();i++){
            int to=st[x][i];
            if(to==pre)continue;
            dfs(to,x);
            nw1+=dp[to];
            nw2+=size[to];
         }
    }
    double expectedLength(vector <int> A, vector <int> B, vector <int> f) {
        int n=A.size()+1;
        int m=f.size();

        double ans=0;
        double p=1.0/(n-1);
        memset(dp,0,sizeof(dp));
        memset(cnt,0,sizeof(cnt));
        memset(size,0,sizeof(size));
        memset(mark,0,sizeof(mark));
        for(int i=0;i<n;i++)st[i].clear();

        for(int i=0;i<n-1;i++){
            int x=A[i];
            int y=B[i];
            st[x].push_back(y);
            st[y].push_back(x);
        }
        for(int i=0;i<m;i++)cnt[f[i]]++;
        dfs(0,-1);
        for(int i=0;i<n;i++){
            for(int j=0;j<st[i].size();j++){
                int to=st[i][j];
                if(mark[i][to]||mark[to][i])continue;
                mark[i][to]=mark[to][i]=1;
                int cntL1=m-dp[to];
                int cntR1=size[to];
                int cntL2=dp[to];
                int cntR2=n-size[to];
                double p1=pow(1.0*p*cntR1,cntL1);
                double p2=pow(1.0*p*cntR2,cntL2);
                if(!p1)p1=1.0;
                if(!p2)p2=1.0;
                ans+=p1*p2;
            }
        }
        return ans;
    }
};
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值