Time Limit: 10 Sec
Memory Limit: 128 MB
题目分析
突然发现这种类型的路径期望总是高斯消元
一开始想求每条边的期望经过次数,但浮点数又不能异或
考虑到异或运算每位都是独立的,于是考虑按位处理
设当前处理第
i
i
i位,
f
u
f_u
fu表示
u
u
u到
n
n
n路径异或和第
i
i
i位为1的概率
列出方程
f
u
=
1
d
e
g
[
u
]
(
∑
e
(
u
,
v
)
,
w
=
0
f
v
+
∑
e
(
u
,
v
)
,
w
=
1
(
1
−
f
v
)
)
f_u=\frac{1}{deg[u]}(\sum_{e(u,v),w=0}f_v+\sum_{e(u,v),w=1}(1-f_v))
fu=deg[u]1(∑e(u,v),w=0fv+∑e(u,v),w=1(1−fv))
移项得
d
e
g
[
u
]
∗
f
u
−
∑
e
(
u
,
v
)
,
w
=
0
f
v
+
∑
e
(
u
,
v
)
,
w
=
1
f
v
=
∑
e
(
u
,
v
)
,
w
=
1
1
deg[u]*f_u-\sum_{e(u,v),w=0}f_v+\sum_{e(u,v),w=1}f_v=\sum_{e(u,v),w=1}1
deg[u]∗fu−∑e(u,v),w=0fv+∑e(u,v),w=1fv=∑e(u,v),w=11
高斯消元求解得
f
1
f_1
f1,令ans累加
a
n
s
+
=
f
1
∗
2
i
ans+=f_1*2^i
ans+=f1∗2i
复杂度约为 O ( n 3 l o g w ) O(n^3logw) O(n3logw)
#include<iostream>
#include<cmath>
#include<algorithm>
#include<queue>
#include<cstring>
#include<cstdio>
using namespace std;
typedef long long lt;
typedef double dd;
int read()
{
int f=1,x=0;
char ss=getchar();
while(ss<'0'||ss>'9'){if(ss=='-')f=-1;ss=getchar();}
while(ss>='0'&&ss<='9'){x=x*10+ss-'0';ss=getchar();}
return f*x;
}
const int maxn=210;
int n,m;
dd a[maxn][maxn],ans[maxn],c[maxn];
struct node{int v,w,nxt;}E[50010];
int head[maxn],tot;
int deg[maxn],mx;
void add(int u,int v,int w)
{
E[++tot].nxt=head[u];
E[tot].v=v; E[tot].w=w;
head[u]=tot;
}
void gauss()
{
for(int i=1;i<=n;++i)
{
int r=i;
for(int j=i+1;j<=n;++j)
if(fabs(a[j][i])>fabs(a[r][i])) r=j;
if(r!=i) swap(a[r],a[i]);
dd f=a[i][i];
for(int j=1;j<=n+1;++j) a[i][j]/=f;
for(int j=1;j<=n;++j)
if(i!=j){
f=a[j][i];
for(int k=1;k<=n+1;++k)
a[j][k]-=f*a[i][k];
}
}
for(int i=n;i>=1;--i)
{
ans[i]=a[i][n+1];
for(int j=i+1;j<=n;++j)
ans[i]-=a[i][j]*ans[j];
}
}
void mat(int k)
{
memset(a,0,sizeof(a));
a[n][n]=1;
for(int u=1;u<n;++u)
{
a[u][u]=(dd)deg[u];
for(int i=head[u];i;i=E[i].nxt)
{
int v=E[i].v;
if(E[i].w&k) a[u][v]+=1.0,a[u][n+1]+=1.0;
else a[u][v]-=1.0;
}
}
}
int main()
{
n=read(),m=read();
for(int i=1;i<=m;++i)
{
int u=read(),v=read(),w=read(); mx=max(mx,w);
add(u,v,w); deg[u]++;
if(u!=v) add(v,u,w),deg[v]++;
}
dd res=0;
for(int i=1;i<=mx;i<<=1)
{
mat(i); gauss();
res+=ans[1]*(dd)i;
}
printf("%.3lf",res);
return 0;
}