bzoj 2337: [HNOI2011]XOR和路徑
阿新 • • 發佈:2017-07-25
bzoj long desc hnoi2011 處理 scan problem 發現 一次
Description
Input
Output
Sample Input
Sample Output
HINT
Source
Day2
終於把這個史前遺留的坑給填了。。。
首先異或的話由位無關性,可以按位處理。。。
那麽對於每一位,設f[i]表示從i出發第一次到達n且xor和為1的概率,out[i]為i的出邊,那麽轉移就比較容易了。。。
if(w(i,j)&xxx) f[i]+=(1-f[j)/out[i];// 這條邊該位為1,需要xor上0,xor和才為1
else f[i]+=f[j]/out[i];//同上。。。
但是這個有環,而且可以走重邊自環,肯定是不能dp的,
但是我們發現對於每個f[i]=f[j]/out[i]+(1-f[j‘]/out[i])...都是一個線性方程。。。所以這是一個線性方程組。。。
然後我們由已知f[n]=1,所以可以用高斯消元解決。。。很妙啊。。。
// MADE BY QT666 #include<cstdio> #include<algorithm> #include<cmath> #include<iostream> #include<cstring> using namespace std; typedef long long ll; const int N=150; const int M=200050; int out[N]; int head[M],nxt[M],to[M],cnt,w[M],n,m; double a[N][N],ans; void gauss() { for(int i=1;i<=n;i++) { int t=i; while(!a[t][i]) t++; if(i!=t) swap(a[t],a[i]); double k=a[i][i]; for(int j=i;j<=n+1;j++) a[i][j]/=k; for(int j=1;j<=n;j++) if(j!=i&&a[j][i]) { k=a[j][i]; for(int p=i;p<=n+1;p++) a[j][p]-=k*a[i][p]; } } } void lnk(int x,int y,int z){ to[++cnt]=y,nxt[cnt]=head[x],w[cnt]=z,head[x]=cnt; } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ int u,v,val;scanf("%d%d%d",&u,&v,&val); lnk(u,v,val);out[u]++; if(u!=v) out[v]++,lnk(v,u,val); } int gg; for(int k=0;k<=30;k++){ if(k==0) gg=1;else gg=gg<<1; memset(a,0,sizeof(a)); for(int i=1;i<n;i++){ a[i][i]=-1.0; for(int j=head[i];j;j=nxt[j]){ int y=to[j]; if(w[j]&gg){ a[i][y]-=1.0/out[i],a[i][n+1]-=1.0/out[i]; } else a[i][y]+=1.0/out[i]; } } a[n][n]=-1.0;gauss();ans+=a[1][n+1]*gg; } printf("%.3f\n",ans); return 0; }
bzoj 2337: [HNOI2011]XOR和路徑