bzoj2337: [HNOI2011]XOR和路径

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2337

 

2337: [HNOI2011]XOR和路径

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 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 */
View Code

 

posted @ 2016-08-19 15:11  I'mLS  阅读(178)  评论(0编辑  收藏  举报