您的位置:首页 > 其它

【BZOJ】2337: [HNOI2011]XOR和路径 期望+高斯消元

2018-03-08 21:11 387 查看

【题意】给定n个点m条边的带边权无向连通图(有重边和自环),在每个点随机向周围走一步,求1到n的期望路径异或值。n<=100,wi<=10^9。

【算法】期望+高斯消元

【题解】首先异或不满足期望的线性,所以考虑拆位。

对于每一个二进制位,经过边权为0仍是x,经过边权为1变成1-x(转化成减法才满足期望的线性)。

设f[x]表示点x到n的路径xor期望,f
=0,根据全期望公式:

$$f[i]=\sum_{j}\frac{f[j]}{out[i]}\ \ , \ \ w(i,j)=0$$

$$f[i]=\sum_{j}\frac{1-f[j]}{out[i]}\ \ , \ \ w(i,j)=1$$

因为有循环所以用高斯消元求解,复杂度O(n^3*log wi)。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn=110;
struct edge{int v,w,from;}e[maxn*maxn*2];
int n,m,first[maxn],tot,out[maxn];
long double a[maxn][maxn],ans;
void insert(int u,int v,int w){tot++;e[tot].v=v;e[tot].w=w;e[tot].from=first[u];first[u]=tot;out[u]++;}
void gauss(){
for(int i=1;i<n;i++){
int r=i;
for(int j=i+1;j<=n;j++)if(fabs(a[j][i])>fabs(a[r][i]))r=j;
if(r!=i)for(int j=i;j<=n+1;j++)swap(a[i][j],a[r][j]);
for(int j=i+1;j<=n;j++)
for(int k=n+1;k>=i;k--)
a[j][k]-=a[j][i]/a[i][i]*a[i][k];
}
for(int i=n;i>=1;i--){
for(int 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);
for(int i=1;i<=m;i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
insert(u,v,w);
if(u!=v)insert(v,u,w);//
}
for(int k=0;k<=30;k++){
memset(a,0,sizeof(a));//
for(int x=1;x<n;x++){
for(int i=first[x];i;i=e[i].from){
if(e[i].w&(1<<k)){
a[x][e[i].v]--;//
a[x][n+1]--;
}
else a[x][e[i].v]++;
}
a[x][x]-=out[x];//
}
a

=1;
gauss();
ans+=a[1][n+1]*(1<<k);
}
printf("%.3Lf",ans);
return 0;
}
View Code

 

注意:

1.方程组右边是常数项。

2.自环不要重复加边。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: