solution
首先想对于每个二进制位分别计算。
用(f[i])表示第(i)个点走到(n)异或和为(1)的概率。用(du[i])表示第(i)个点的度数,那么就有
[f[u]=frac{1}{du[u]}(sumlimits_{w(u,v)=1}(1-f[v])+sumlimits_{w(u,v)=0}f[v])\ Rightarrow du[u]f[u]=sumlimits_{w(u,v)=1}1-sumlimits_{w(u,v)=1}f[v]+sumlimits_{w(u,v)=0}f[v]\ Rightarrow sumlimits_{w(u,v)=1}1=du[u]f[u]+sumlimits_{w(u,v)=1}f[v]-sumlimits_{w(u,v)=0}f[v]
]
然后高斯消元就行了。
对于第(x)位的答案就是(2^x imes a[1][1])
code
/*
* @Author: wxyww
* @Date: 2020-04-27 18:46:32
* @Last Modified time: 2020-04-27 19:31:34
*/
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
#include<ctime>
using namespace std;
typedef long long ll;
const int N = 110;
ll read() {
ll x = 0,f = 1;char c = getchar();
while(c < '0' || c > '9') {
if(c == '-') f = -1; c = getchar();
}
while(c >= '0' && c <= '9') {
x = x * 10 + c - '0'; c = getchar();
}
return x * f;
}
struct node {
int v,nxt,w;
}e[N * N * 2];
int du[N],head[N],ejs;
void add(int u,int v,int w) {
e[++ejs].v = v;e[ejs].nxt = head[u];head[u] = ejs;e[ejs].w = w;
}
int n,m;
double a[N][N];
void pre(int x) {
x = (1 << x);
a[n][n] = 1;//f[n] = 1!!!
memset(a,0,sizeof(a));
for(int u = 1;u < n;++u) {//u < n !!!!
a[u][u] = du[u];
for(int i = head[u];i;i = e[i].nxt) {
int v = e[i].v;
if(e[i].w & x) a[u][v]++,a[u][n + 1]++;
else a[u][v]--;
}
}
}
void Guass() {
for(int i = 1;i <= n;++i) {
int t = i;
for(int j = i + 1;j <= n;++j)
if(a[j][i] > a[t][i]) t = j;
if(fabs(a[t][i]) < 1e-8) continue;
swap(a[i],a[t]);
for(int j = 1;j <= n;++j) {
if(j == i) continue;
double tmp = a[j][i] / a[i][i];
for(int k = 1;k <= n + 1;++k)
a[j][k] -= a[i][k] * tmp;
}
}
}
int main() {
n = read(),m = read();
for(int i = 1;i <= m;++i) {
int u = read(),v = read(),w = read();
add(u,v,w);
du[u]++;
if(u != v)
du[v]++,add(v,u,w);
}
double ans = 0;
for(int i = 30;i >= 0;--i) {
pre(i);
Guass();
ans += (a[1][n + 1] / a[1][1]) * (1 << i);
}
printf("%.3lf
",ans);
return 0;
}
/*
3 3
1 2 4
1 3 5
*/