bzoj2337 XOR路径 高斯消元

来源:互联网 发布:多玩我的世界盒子js 编辑:程序博客网 时间:2024/04/30 01:14

       遇到位运算,还是一位一位来。假设考虑二进制第k位,那么

       令f[i]表示以到达i时,第i位存在的期望,那么对于所有与i相连的j,如果(i,j)的第k位为1,那么f[i]+=(1-f[j])/i的入度,否则f[i]+=f[j]/i的入度。

       这样看起来有n个方程,但是有一个是没用的,随便去掉一个。然后实际上令从n到1是等价的,只需要让f[n]=0即可。

AC代码如下:

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#define eps 1e-10#define N 105#define M 20005using namespace std;int n,m,tot,bin[35],etr[N],fst[N],pnt[M],len[M],nxt[M];double a[N][N];void add(int x,int y,int z){etr[y]++; pnt[++tot]=y; len[tot]=z; nxt[tot]=fst[x]; fst[x]=tot;}void gas(){int i,j,k;for (i=1; i<=n; i++){for (j=i; j<=n; j++) if (a[j][i]) break;if (j>n) continue; if (i!=j) swap(a[i],a[j]);for (k=i+1; k<=n; k++)if (fabs(a[k][i])>eps){double x=a[k][i]/a[i][i];for (j=n+1; j>=i; j--)a[k][j]-=x*a[i][j];}}for (i=n; i; i--){for (j=i+1; j<=n; j++) a[i][n+1]-=a[i][j]*a[j][n+1];a[i][n+1]/=a[i][i];}}int main(){scanf("%d%d",&n,&m); int i,x,p,mx=0;for (i=1; i<=m; i++){int x,y,z; scanf("%d%d%d",&x,&y,&z);add(x,y,z); if (x!=y) add(y,x,z);mx=max(mx,z);}bin[0]=1; for (i=1; i<=30; i++) bin[i]=bin[i-1]<<1;double ans=0;for (i=0; bin[i]<=mx; i++){memset(a,0,sizeof(a));for (x=1; x<=n; x++){a[x][x]=1;for (p=fst[x]; p; p=nxt[p]){int y=pnt[p];if (len[p]&bin[i]){ a[x][y]+=1.0/etr[x]; a[x][n+1]+=1.0/etr[x]; }else a[x][y]-=1.0/etr[x];}}for (x=1; x<=n+1; x++) a[n][x]=0; a[n][n]=1;gas(); ans+=a[1][n+1]*bin[i];}printf("%.3f\n",ans);return 0;}


by lych

2016.3.7

0 0
原创粉丝点击