http://www.lydsy.com/JudgeOnline/problem.php?id=2337
高斯消元解期望方程。
按位考虑
首先从n出来的边不能算!
然后期望要倒着推
因为我们不知道1到n的期望但是我们知道n到n的期望
并且
xor
的期望
≤1
则有
if(dis==0)E(u)=∑E(v)/deg[u]
elseE(u)=∑(1−E(v))/deg[u]
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define maxn 100010
using namespace std;
int n, m;
struct Edge{int u, v, dis;};
Edge edge[maxn], G[maxn];
int cnt, deg[maxn];
void add(int u, int v, int w){
cnt ++;
edge[cnt].v = v;
edge[cnt].u = u;
edge[cnt].dis = w;
deg[u] ++;
}
double a[110][110];
void Gauss(int n){
for(int i = 1; i <= n; i ++){
for(int j = i; j <= n; j ++){
if(a[j][i]){
for(int k = 1; k <= n+1; k ++)
swap(a[i][k], a[j][k]);
for(int k = 1; k <= n+1; k ++)
if(k != i)a[i][k] /= a[i][i];
a[i][i] = 1;
break;
}
}
if(a[i][i] == 0)continue;
for(int j = 1; j <= n; j ++){
if(j == i || a[j][i] == 0)continue;
double t = a[j][i];
for(int k = i; k <= n+1; k ++)
a[j][k] -= t * a[i][k];
}
}
}
void Debug(int n){
for(int i = 1; i <= n; i ++){
for(int j = 1; j <= n+1; j ++)
printf("%.2lf ", a[i][j]);
printf("\n");
}puts("");
}
double solve(int p){
memset(a, 0, sizeof a);
/*
if(dis == 1)E(u) = E(v) * 1/deg[u]
else E(u) = (1 - E(v)) * 1/deg[u]
*/
for(int i = 1; i <= n; i ++)a[i][i] = 1;
for(int i = 1; i <= cnt; i ++){
int u = edge[i].u, v = edge[i].v;
if(u == n)continue;
if(edge[i].dis >> p & 1){
a[u][v] += 1.0 / deg[u];
a[u][n+1] += 1.0 / deg[u];
}
else a[u][v] -= 1.0 / deg[u];
}
Gauss(n);
return a[1][n+1];
}
int main(){
scanf("%d%d", &n, &m);
int u, v, w;
for(int i = 1; i <= m; i ++){
scanf("%d%d%d", &u, &v, &w);
add(u, v, w);
if(v != u)add(v, u, w);
}
double ans = 0;
for(int i = 30; i >= 0; i --)
ans += solve(i) * (1 << i);
printf("%.3lf\n", ans);
return 0;
}