不妨用
用
那麼答案顯然等於
如何考慮求
直接來說基環樹上的情況,樹上的情況可以看做基環樹中環的某個點爲根的子樹的情況。
首先
首先自底向上DP,求出
那麼有
這樣可以求出所有的
如何考慮不在環上的點,假設我們已經求出了環上點的
用
那麼考慮求環上點的
我們不妨對點進行編號,假設從
最後不要忘記將順時針和逆時針的答案加起來/2。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=100005;
int n,m,cnt,cir[25],head[N],next[N<<1],list[N<<1],from[N];
double key[N<<1],down[N],up[N],son[N],fa[N],pre[N];
bool vis[N];
inline int read()
{
int a=0,f=1; char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}
while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}
return a*f;
}
inline void insert(int x,int y,double z)
{
next[++cnt]=head[x];
head[x]=cnt;
list[cnt]=y;
key[cnt]=z;
}
void dfs1(int x,int f)
{
for (int i=head[x];i;i=next[i])
if (list[i]!=f&&!vis[list[i]])
dfs1(list[i],x),son[x]++;
if (!son[x]) return;
for (int i=head[x];i;i=next[i])
if (list[i]!=f&&!vis[list[i]])
down[x]+=down[list[i]]+key[i];
down[x]/=son[x];
}
void dfs2(int x,int f)
{
if (!son[x]) return;
for (int i=head[x];i;i=next[i])
if (list[i]!=f&&!vis[list[i]]) up[list[i]]+=key[i];
if (son[x]+fa[x]>1)
for (int i=head[x];i;i=next[i])
if (list[i]!=f&&!vis[list[i]])
up[list[i]]+=(down[x]*son[x]-down[list[i]]-key[i]+up[x]*fa[x])/(son[x]-1+fa[x]);
for (int i=head[x];i;i=next[i])
if (list[i]!=f&&!vis[list[i]]) dfs2(list[i],x);
}
void dfs_circle(int x)
{
vis[x]=true;
for (int i=head[x];i;i=next[i])
if (!vis[list[i]]) from[list[i]]=x,pre[list[i]]=key[i],dfs_circle(list[i]);
else if (list[i]!=from[x])
{
from[list[i]]=x; pre[list[i]]=key[i];
for (int j=x;j!=list[i];j=from[j]) cir[++cir[0]]=j;
cir[++cir[0]]=list[i];
return;
}
}
int main()
{
n=read(); m=read();
for (int i=1;i<=m;i++)
{
int u=read(),v=read();
double w;
scanf("%lf",&w);
insert(u,v,w); insert(v,u,w);
}
if (m==n-1)
{
for (int i=1;i<=n;i++) fa[i]=1;
memset(vis,0,sizeof(vis));
fa[1]=0;
dfs1(1,0);
dfs2(1,0);
}
else
{
dfs_circle(1);
for (int i=1;i<=n;i++) fa[i]=1;
for (int i=1;i<=cir[0];i++) fa[cir[i]]=2;
memset(vis,0,sizeof(vis));
for (int i=1;i<=cir[0];i++) vis[cir[i]]=1;
for (int i=1;i<=cir[0];i++) dfs1(cir[i],0);
// for (int i=1;i<=cir[0];i++)
// cout << from[cir[i]] << " "; cout << endl;
// for (int i=1;i<=cir[0];i++)
// cout << pre[cir[i]] << " ";
// cout <<"!!!!!!!";
for (int i=1;i<=cir[0];i++)
{
double P;
P=1.0;
for (int j=1;j<cir[0];j++)
{
int now=cir[(i+j-1)%cir[0]+1];
// cout << cir[i] << " " << now << " " << pre[cir[(i+j-2)%cir[0]+1]] << endl;
if (j!=cir[0]-1)
up[cir[i]]+=P*(pre[cir[(i+j-2)%cir[0]+1]]+down[now]*son[now]/(son[now]+1));
else
up[cir[i]]+=P*(pre[cir[(i+j-2)%cir[0]+1]]+down[now]);
P/=son[now]+1;
}
// cout << endl;
P=1.0;
for (int j=1;j<cir[0];j++)
{
int now=cir[(i-j+cir[0]-1)%cir[0]+1];
// cout << cir[i] << " " << now << " " << pre[now] << endl;
if (j!=cir[0]-1)
up[cir[i]]+=P*(pre[now]+down[now]*son[now]/(son[now]+1));
else
up[cir[i]]+=P*(pre[now]+down[now]);
P/=son[now]+1;
}
// cout << endl;
up[cir[i]]/=2;
}
for (int i=1;i<=cir[0];i++) dfs2(cir[i],0);
}
// for (int i=1;i<=cir[0];i++)
// cout << son[cir[i]] << " " ;
double ans=0.0;
for (int i=1;i<=n;i++)
ans+=(down[i]*son[i]+up[i]*fa[i])/(son[i]+fa[i]);
printf("%.5lf\n",ans/n);
return 0;
}