[BZOJ2337][HNOI2011]XOR和路径(概率+高斯消元)

直接不容易算,考虑拆成位处理。

设f[i]表示i到n的期望路径异或和(仅考虑某一位),则$f[y]=\sum\limits_{exist\ x1\to y=0}\frac{f[x1]}{d[x1]}+\sum\limits_{exist\ x2\to y=1}\frac{1-f[x2]}{d[x2]}$。

对于重边,直接在系数上+1即可。对于自环,只计算一次度数即可。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 #define rep(i,l,r) for (int i=l; i<=r; i++)
 6 typedef long long ll;
 7 using namespace std;
 8 
 9 const int N=110,M=10010;
10 int n,m,d[N];
11 double ans,a[N][N];
12 struct E{ int x,y,w; }e[M];
13 double Abs(double x){ return (x<0) ? -x : x; }
14 
15 double cal(int S){
16     memset(a,0,sizeof(a));
17     rep(i,1,m){
18         if (e[i].w&S){
19             a[e[i].x][e[i].y]+=1; a[e[i].x][n+1]+=1;
20             if (e[i].x!=e[i].y) a[e[i].y][e[i].x]+=1,a[e[i].y][n+1]+=1;
21         }else{
22             a[e[i].x][e[i].y]-=1;
23             if (e[i].x!=e[i].y) a[e[i].y][e[i].x]-=1;
24         }
25     }
26     rep(i,1,n+1) a[n][i]=0;
27     rep(i,1,n) a[i][i]+=d[i];
28     rep(i,1,n){
29         int k=i;
30         rep(j,i+1,n) if (Abs(a[j][i])>Abs(a[k][i])) k=j;
31         rep(j,i,n+1) swap(a[k][j],a[i][j]);
32         rep(j,i+1,n){
33             double t=a[j][i]/a[i][i];
34             rep(k,i,n+1) a[j][k]-=a[i][k]*t;
35         }
36     }
37     for (int i=n; i; i--){
38         rep(j,i+1,n) a[i][n+1]-=a[i][j]*a[j][n+1];
39         a[i][n+1]/=a[i][i];
40     }
41     return a[1][n+1];
42 }
43 
44 int main(){
45     freopen("bzoj2337.in","r",stdin);
46     freopen("bzoj2337.out","w",stdout);
47     scanf("%d%d",&n,&m);
48     rep(i,1,m){
49         scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].w); d[e[i].x]++;
50         if (e[i].y!=e[i].x) d[e[i].y]++;
51     }
52     for (int i=1<<30; i; i>>=1) ans+=cal(i)*i;
53     printf("%.3lf\n",ans);
54     return 0;
55 }

 

posted @ 2018-10-19 00:09  HocRiser  阅读(168)  评论(0编辑  收藏  举报