标签:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 100010
using namespace std;
int n,m,cnt,tot;
struct node
{
int from,to,val,next;
}edge[N<<1];
int head[N];
int size[N];
int fa[N];
int cntfa[N];
int v[N];
int inc[N];
int cir[N];
int pre[N];
int nex[N];
double sum[N];
double up[N];
double dis[N];
double down[N];
void init()
{
memset(head,-1,sizeof(head));
cnt=1;
}
void edgeadd(int from,int to,int val)
{
edge[cnt].from=from,edge[cnt].to=to,edge[cnt].val=val;
edge[cnt].next=head[from];
head[from]=cnt++;
}
int flag;
void getcir(int now,int ff)
{
fa[now]=ff;
v[now]=1;
for(int i=head[now];i!=-1;i=edge[i].next)
{
if(flag)return;
int to=edge[i].to;
if(to==ff)continue;
if(v[to]!=0)
{
cir[++tot]=to;
inc[to]=tot;
cntfa[to]=2;
int tmp=now;
do
{
cir[++tot]=tmp;
cntfa[tmp]=2;
inc[tmp]=tot;
tmp=fa[tmp];
}while(tmp!=to);
flag=1;return ;
}else
{
getcir(to,now);
}
}
}
double map[25][25];
int ccccnt;
void dfscir(int now,int fa)
{
for(int i=head[now];i!=-1;i=edge[i].next)
{
int to=edge[i].to;
if(!inc[to]||to==fa||ccccnt==tot)continue;
ccccnt++;
pre[to]=now;
nex[now]=to;
dfscir(to,now);
map[inc[to]][inc[now]]=map[inc[now]][inc[to]]=(double)edge[i].val;
break;
}
}
void dfs(int now,int fa)
{
for(int i=head[now];i!=-1;i=edge[i].next)
{
int to=edge[i].to;
if(to==fa||inc[to])continue;
cntfa[to]=1;
dfs(to,now);
dis[to]=edge[i].val;
size[now]++;
sum[now]+=down[to]+edge[i].val;
}
if(size[now]!=0)down[now]=sum[now]/(double)size[now];
}
void dfs3(int now,int fa,int root)
{
if(now!=1)
{
double tmp=sum[fa]-dis[now]+up[fa];
if(size[now]!=0)tmp-=sum[now]/size[now];
if(fa==1)up[now]=tmp/(size[fa]-1);
else up[now]=tmp/size[fa];
up[now]+=dis[now];
}
for(int i=head[now];i!=-1;i=edge[i].next)
{
int to=edge[i].to;
if(to==fa)continue;
dfs3(to,now,root);
}
}
void dfs2(int now,int fa,int root)
{
if(now!=root)
{
double tmp=sum[fa]-dis[now]+up[fa];
if(inc[fa])tmp+=up[fa];
if(size[now]!=0)tmp-=sum[now]/size[now];
if(inc[fa])up[now]=tmp/(size[fa]+1);
else up[now]=tmp/size[fa];
up[now]+=dis[now];
}
for(int i=head[now];i!=-1;i=edge[i].next)
{
int to=edge[i].to;
if(to==fa)continue;
dfs2(to,now,root);
}
}
double ans;
int main()
{
init();
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
edgeadd(x,y,z);
edgeadd(y,x,z);
}
if(m==n-1)
{
dfs(1,-1);
dfs3(1,-1,1);
for(int i=1;i<=n;i++)
{
if(i==1)ans+=(sum[i]+up[i])/(double)(size[i]);
else ans+=(sum[i]+up[i])/(double)(size[i]+1);
}
ans/=(double)n;
printf("%.5lf\n",ans);
}else
{
getcir(1,-1);
dfscir(cir[1],-1);
for(int i=1;i<=n;i++)if(inc[i])dfs(i,-1);
for(int i=1;i<=tot;i++)
{
double k=1;
int now=cir[i];
for(int j=nex[now];j!=now;j=nex[j])
{
if(nex[j]!=now)
{
up[now]+=k*(map[inc[pre[j]]][inc[j]]+down[j]*size[j]/(size[j]+1));
}else
{
up[now]+=k*(map[inc[pre[j]]][inc[j]]+down[j]);
}
k/=(size[j]+1);
}
k=1;
for(int j=pre[now];j!=now;j=pre[j])
{
if(pre[j]!=now)
{
up[now]+=k*(map[inc[nex[j]]][inc[j]]+down[j]*size[j]/(size[j]+1));
}else
{
up[now]+=k*(map[inc[nex[j]]][inc[j]]+down[j]);
}
k/=(size[j]+1);
}
up[now]/=2.0;
}
for(int i=1;i<=tot;i++)
{
int now=cir[i];
for(int j=head[now];j!=-1;j=edge[j].next)
{
int to=edge[j].to;
if(!inc[to])dfs2(to,now,now);
}
}
double ans=0;
for(int i=1;i<=n;i++)
{
if(inc[i])
{
ans+=(up[i]*2+down[i]*size[i])/(double)(2+size[i]);
}else ans+=(up[i]+down[i]*size[i])/(double)(1+size[i]);
}
printf("%.5lf\n",ans/(double)n);
}
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
BZOJ 2878 [Noi2012]迷失游乐园 树形期望DP+基环树
标签:
原文地址:http://blog.csdn.net/wzq_qwq/article/details/47319809