1. 程式人生 > >[BZOJ2337][HNOI2011]XOR和路徑(概率+高斯消元)

[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 }