bzoj2337: [HNOI2011]XOR和路径
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2337
因为是xor,我们按位处理,可以得到如果权值(w&(1<<i)),那么ex[u]+=1/d[u]*(1-f[v]),否则ex[u]+=1/d[u]*f[v],然后高斯消元。
注意几个点,终点连出去的边全部不用考虑,不用去判断权值w>0的情况,令a[n][n]=1,有重边就不要作死开邻接矩阵。
#include<cstring> #include<cstdio> #include<algorithm> #include<cmath> #include<iostream> #define rep(i,l,r) for (int i=l;i<=r;i++) #define down(i,l,r) for (int i=l;i>=r;i--) #define clr(x,y) memset(x,y,sizeof(x)) #define maxn 210 #define ll long long #define eps 1e-6 using namespace std; struct data{int obj,pre,c; }e[200500]; int d[maxn],bin[maxn],head[maxn]; double a[maxn][maxn],ans; int n,x,y,z,m,tot; void insert(int x,int y,int z){ d[x]++; e[++tot].obj=y; e[tot].pre=head[x]; e[tot].c=z; head[x]=tot; } ll read(){ ll x=0,f=1; char ch=getchar(); while (!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();} while (isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();} return x*f; } void solve(int n){ int now; double t; rep(i,1,n){ now=i; while (fabs(a[now][i])<=eps) now++; if (now>n) continue; if (now!=i) rep(j,1,n+1) swap(a[i][j],a[now][j]); t=a[i][i]; rep(j,1,n+1) a[i][j]/=t; rep(j,1,n) if (j!=i){ t=a[j][i]; rep(k,1,n+1) a[j][k]-=t*a[i][k]; } } } int main(){ bin[0]=1; rep(i,1,30) bin[i]=bin[i-1]*2; n=read(); m=read(); rep(i,1,m){ int x,y,z; x=read(); y=read(); z=read(); insert(x,y,z); if (x!=y) insert(y,x,z); } ans=0; rep(o,0,30){ clr(a,0); rep(u,1,n-1){ a[u][u]=1.0; for (int j=head[u];j;j=e[j].pre){ int v=e[j].obj; if (e[j].c&bin[o]) a[u][n+1]+=1.0/d[u],a[u][v]+=1.0/d[u]; else a[u][v]-=1.0/d[u]; } } a[n][n]=1.0; solve(n); ans+=a[1][n+1]*bin[o]; } printf("%.3lf\n",ans); return 0; }