# solution

$f[i]$表示第$i$个点走到$n$异或和为$1$的概率。用$du[i]$表示第$i$个点的度数，那么就有

$f[u]=\frac{1}{du[u]}(\sum\limits_{w(u,v)=1}(1-f[v])+\sum\limits_{w(u,v)=0}f[v])\\ \Rightarrow du[u]f[u]=\sum\limits_{w(u,v)=1}1-\sum\limits_{w(u,v)=1}f[v]+\sum\limits_{w(u,v)=0}f[v]\\ \Rightarrow \sum\limits_{w(u,v)=1}1=du[u]f[u]+\sum\limits_{w(u,v)=1}f[v]-\sum\limits_{w(u,v)=0}f[v]$

# 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\n",ans);

return 0;
}

/*
3 3
1 2 4
1 3 5
*/

posted @ 2020-04-27 19:42  wxyww  阅读(...)  评论(...编辑  收藏