bzoj2337: [HNOI2011]XOR和路径
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2337
2337: [HNOI2011]XOR和路径
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 933 Solved: 538
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
Sample Output
HINT
Source
由于期望的线性性质,我们可以分别算每一位的期望,然后加起来就是答案。
设f[i]为从1走到i的当前位的期望,d[i]为i的出度,则:
val[i][son[i]]当前位为1:f[son[i]]+=f[i]*1.0/d[i];
val[i][son[i]]当前位为0:f[son[i]]-=f[i]*1.0/d[i];
这两个式子还是很好理解的。
然后我们就可以列出一些方程组,用高斯消元就可以求出答案了。
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<cmath> 5 #define maxn 110 6 #define maxm 10010 7 using namespace std; 8 typedef double ld; 9 int n,m,tot,h[maxn],way[maxm*2],next[maxm*2],val[maxm*2],d[maxn]; 10 ld ans,a[maxn][maxn]; 11 void insert(int x,int y,int z){way[++tot]=y;next[tot]=h[x];h[x]=tot;val[tot]=z;++d[x];} 12 void gauss(){ 13 for(int i=1;i<=n;i++){ 14 ld maxv=0;int maxi; 15 for(int j=i;j<=n;j++)if(fabs(a[j][i])>maxv)maxi=j,maxv=fabs(a[j][i]); 16 if(maxi!=i)for(int j=1;j<=n+1;j++)swap(a[i][j],a[maxi][j]); 17 ld pp=a[i][i];for(int j=1;j<=n+1;j++)a[i][j]/=pp; 18 for(int j=1;j<=n;j++){ 19 pp=a[j][i];if(j==i)continue; 20 for(int k=1;k<=n+1;k++)a[j][k]-=pp*a[i][k]; 21 } 22 } 23 } 24 int main(){ 25 scanf("%d%d",&n,&m); 26 for(int i=1,x,y,z;i<=m;i++){ 27 scanf("%d%d%d",&x,&y,&z); 28 insert(x,y,z);if(x!=y)insert(y,x,z); 29 } 30 for(int k=0;k<=30;k++){ 31 memset(a,0,sizeof(a)); 32 for(int i=1;i<=n-1;i++){ 33 a[i][i]=1; 34 for(int j=h[i];j;j=next[j]){ 35 if(val[j]&(1<<k))a[i][way[j]]+=1.0/d[i],a[i][n+1]+=1.0/d[i]; 36 else a[i][way[j]]-=1.0/d[i]; 37 } 38 } 39 a[n][n]=1;gauss();ans+=a[1][n+1]*(1<<k); 40 } 41 printf("%.3lf\n",ans); 42 return 0; 43 } 44 /* 45 2 2 46 1 1 2 47 1 2 3 48 49 */