传送门
SOL
题意:给一个可能有一个环的树,定义一条合法的路径为从某一起点出发,随机在未走过的点中选择,直到走不动。求从任一点出发的路径长度的期望值。
//基环树的确不需要学啊。。。自己yy就出来了。
一、先处理树上的情况。
这是一个很显然的树上期望dp,但是为了保证统计的方案是合法的,我们要把向上走和向下走两种情况分开讨论。
d p [ u ] [ d o w n ] = ( ∑ d p [ s o n [ u ] [ d o w n ] ) / s [ u ] dp[u][down]=(\sum dp[son[u][down])/s[u] dp[u][down]=(∑dp[son[u][down])/s[u]
d
p
[
u
]
[
u
p
]
=
(
d
p
[
f
a
[
u
]
[
d
o
w
n
]
∗
s
[
f
a
[
u
]
]
−
l
e
n
[
f
a
[
u
]
]
[
u
]
−
d
p
[
u
]
[
d
o
w
n
]
+
d
p
[
f
a
[
u
]
[
u
p
]
)
/
(
s
[
f
a
[
u
]
]
+
1
)
dp[u][up]=(dp[fa[u][down]*s[fa[u]]-len[fa[u]][u]-dp[u][down]+dp[fa[u][up])/(s[fa[u]]+1)
dp[u][up]=(dp[fa[u][down]∗s[fa[u]]−len[fa[u]][u]−dp[u][down]+dp[fa[u][up])/(s[fa[u]]+1)
s
[
u
]
s[u]
s[u]:
u
u
u的儿子数量 ,
d
p
[
u
]
[
d
o
w
n
]
dp[u][down]
dp[u][down]从
u
u
u向下走的期望值。
二、再处理环上的情况。
由于从
i
i
i点出发不能回到自己,首先要分成顺时针和逆时针,并且要以环上每一点为起点出发讨论情况。由于环上点数
≤
20
\le20
≤20,极端情况下时间复杂度为
1
e
5
/
20
∗
20
∗
20
=
2
e
6
1e5/20*20*20=2e6
1e5/20∗20∗20=2e6 ,可以承受.
f
[
u
]
[
0
]
=
l
e
n
[
u
]
[
v
]
+
f
[
v
]
[
0
]
f[u][0]=len[u][v]+f[v][0]
f[u][0]=len[u][v]+f[v][0]
t
m
p
[
u
]
[
0
]
=
(
d
p
[
u
]
[
0
]
∗
s
[
u
]
+
t
m
p
[
v
]
[
0
]
+
l
e
n
[
u
]
[
v
]
)
/
(
s
[
u
]
+
1
)
tmp[u][0]=(dp[u][0]*s[u]+tmp[v][0]+len[u][v])/(s[u]+1)
tmp[u][0]=(dp[u][0]∗s[u]+tmp[v][0]+len[u][v])/(s[u]+1)
f [ u ] f[u] f[u]为当前起点, t m p [ u ] tmp[u] tmp[u]为中间点。
三、合并情况。
i
f
(
!
f
a
[
u
]
)
n
o
w
=
(
f
[
u
]
[
1
]
+
f
[
u
]
[
0
]
+
d
p
[
u
]
[
0
]
∗
s
[
u
]
)
/
(
1.0
∗
(
s
[
u
]
+
2
)
)
;
if(!fa[u])\ now=(f[u][1]+f[u][0]+dp[u][0]*s[u])/(1.0*(s[u]+2));
if(!fa[u]) now=(f[u][1]+f[u][0]+dp[u][0]∗s[u])/(1.0∗(s[u]+2));
e
l
s
e
n
o
w
=
(
d
p
[
u
]
[
1
]
+
d
p
[
u
]
[
0
]
∗
s
[
u
]
)
/
(
1.0
∗
(
s
[
u
]
+
1
)
)
else \ now=(dp[u][1]+dp[u][0]*s[u])/(1.0*(s[u]+1))
else now=(dp[u][1]+dp[u][0]∗s[u])/(1.0∗(s[u]+1))
//DP式子写起来真累。。
CODE
#include<bits/stdc++.h>
#define pf printf
#define sf scanf
#define cs const
#define ll long long
#define db double
using namespace std;
cs int N=1e5+10;
db f[N][2],dp[N][2],tmp[N][2];
int n,m,s[N],fa[N],CN,nxt[N<<1],head[N],w[N<<1],to[N<<1],cnt=1,lasw[N],len[N][2],nxtp[N][2];
bool vis[N],rod[N<<1];
vector <int> g[N];
inline void _add(int u,int v,int ww){
nxt[++cnt]=head[u];head[u]=cnt;to[cnt]=v;w[cnt]=ww;
}
void dfs1(int u){
vis[u]=1;
for(int i=head[u];i;i=nxt[i]){
if(rod[i])continue;
rod[i]=rod[i^1]=1;
if(vis[to[i]]){
nxtp[to[i]][0]=u;nxtp[u][1]=to[i];
len[to[i]][0]=len[u][1]=w[i];
++CN;
for(int v=u;;v=fa[v]){
g[CN].push_back(v);
if(v==to[i])break;
nxtp[v][0]=fa[v];nxtp[fa[v]][1]=v;
len[v][0]=len[fa[v]][1]=lasw[v];
}
}
else{
lasw[to[i]]=w[i];
fa[to[i]]=u;
dfs1(to[i]);
}
}
}
void dfs(int u,bool kd){
if(kd==1){
if(fa[u]){
if(fa[fa[u]])
dp[u][1]=(dp[fa[u]][0]*s[fa[u]]-dp[u][0]-lasw[u]+dp[fa[u]][1])/(1.0*(s[fa[u]]))+lasw[u];
else
dp[u][1]=(dp[fa[u]][0]*s[fa[u]]-dp[u][0]-lasw[u]+f[fa[u]][0]+f[fa[u]][1])/(1.0*(s[fa[u]]+1))+lasw[u];
}
}
for(int i=head[u];i;i=nxt[i]){
int v=to[i];
if(v==fa[u]||vis[v])continue;
fa[v]=u;lasw[v]=w[i];
dfs(v,kd);
if(kd==0){
++s[u];
dp[u][0]+=dp[v][0]+w[i];
}
}
if(kd==0&&s[u])dp[u][0]/=(1.0*(s[u]));
}
namespace work1{
inline void dfs(int u,bool kd){
if(kd==1){
if(fa[u]){
dp[u][1]=lasw[u];
if(fa[fa[u]])
dp[u][1]+=(dp[fa[u]][0]*s[fa[u]]-dp[u][0]-lasw[u]+dp[fa[u]][1])/(1.0*(s[fa[u]]));
else
if(s[fa[u]]>1)dp[u][1]+=(dp[fa[u]][0]*s[fa[u]]-dp[u][0]-lasw[u])/(1.0*(s[fa[u]]-1));
}
}
for(int i=head[u];i;i=nxt[i]){
int v=to[i];
if(v==fa[u]||vis[v])continue;
fa[v]=u;lasw[v]=w[i];
dfs(v,kd);
if(kd==0){
++s[u];
dp[u][0]+=dp[v][0]+w[i];
}
}
if(kd==0&&s[u])dp[u][0]/=(1.0*(s[u]));
}
inline void gather(){
db now=0,ans=0;
for(int u=1;u<=n;++u){
if(!fa[u])
now=dp[u][0];
else
now=(dp[u][1]+dp[u][0]*s[u])/(1.0*(s[u]+1));
ans+=now/(1.0*n);
}
pf("%.5lf",ans);
}
}
inline void calc(int u,cs int &bord,cs int &kd){
if(nxtp[u][kd]==bord){
tmp[u][kd]=dp[u][0];
return;
}
calc(nxtp[u][kd],bord,kd);
if(u^bord)tmp[u][kd]=(dp[u][0]*s[u]+len[u][kd]+tmp[nxtp[u][kd]][kd])/(1.0*(s[u]+1));
else f[u][kd]=len[u][kd]+tmp[nxtp[u][kd]][kd];
}
inline void gather(){
db now=0,ans=0;
for(int u=1;u<=n;++u){
if(!fa[u])
now=(f[u][1]+f[u][0]+dp[u][0]*s[u])/(1.0*(s[u]+2));
else
now=(dp[u][1]+dp[u][0]*s[u])/(1.0*(s[u]+1));
//cout<<u<<' '<<now<<'\n';
ans+=now/(1.0*n);
}
pf("%.5lf",ans);
}
signed main (){
// freopen("data.in","r",stdin);
sf("%d%d",&n,&m);
for(int i=1;i<=m;++i){
int u,v,w;sf("%d%d%d",&u,&v,&w);
_add(u,v,w);_add(v,u,w);
}
if(m^n){
work1::dfs(1,0);
work1::dfs(1,1);
work1::gather();
return 0;
}
for(int u=1;u<=n;++u)if(!vis[u])dfs1(u);
memset(vis,0,sizeof vis);
for(int i=1;i<=CN;++i){
int up=g[i].size();
for(int j=0;j<up;++j){
fa[g[i][j]]=0;vis[g[i][j]]=1;
}
for(int j=0;j<up;++j){
dfs(g[i][j],0);
}
for(int j=0;j<up;++j){
calc(g[i][j],g[i][j],0);
calc(g[i][j],g[i][j],1);
dfs(g[i][j],1);
}
}
gather();
return 0;
}