不注意な
所与\(N \)点、\(M \)の各エッジは、非負整数辺の重みを有するエッジのマップ。
出発の1点目からの人、ポイントに接続された選択の適度な確率の側の散歩、行ってきましたまで(N \)\ドット。
Q:これらのパスの右側にXOR限り期待アップ。
(複数のエッジ描画リングから存在してもよいです)
思考
XORのために、少しずつ、私たちはこれだけ0/1右側の後に、解決するために検討してください。
我々は、セット(DP [U]は\)\表す\(U \)に\(N \)パス所望の確率をする際の排他的論理和の値。
次いで、添加のために\(N \)の各ドットポイント、それは2つのカテゴリに側によって右側に接続されます。
我々セットエッジ重みは側が0に接続されている点である\(V0 \) 、のいずれかに接続されたエッジの重み点側\(V1 \) 、
我々は持つべきである(DP [U] = \ \和\ FRAC { DP [V1]} {サイズ} + \和\ FRAC {1-DP [V2]} {サイズ} \)
約ジェーン得られた:\(DP [U] - \ SUM \ FRAC {Dpの[V1]} {サイズ} + \ SUM \ FRAC {Dpを[V2]} {サイズ} = \ FRAC {SIZ [V2]} {サイズ} \) 、
即\(DP [U] \ CDOT、サイズ\和{Dpの[V1]} + \和{Dpを[V2]} = SIZ [V2] \)
そのようなコンセンサス式\(N-1 \)番目(ただし、\ N(\) DOT)。
そして、左(と共通\(1-N \) )の未知数(\(DP [N] = 0 \) )。
特定のは、のために\(Nは\)ドット、我々は特別な式を開く必要があります:\(DP [N] = 0 \) 。
したがって、我々は解決するためにガウスの消去法を使用することができます。
そして最終的にシーク総複雑である場合、各ビットの相対的寄与である\(O(N ^ 3logV)\) 。
コード
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
#define LD long double
const int MAXN=105;
int N,M;
LD Ans0;
LD Ans[MAXN];
LD A[MAXN][MAXN];
vector<int>P[MAXN],T[MAXN];
LD Abs(LD X){return X<0?-X:X;}
void GX(){
for(int j=1;j<=N;j++){
int Mx=j;
for(int i=j+1;i<=N;i++)
if(Abs(A[i][j])>Abs(A[Mx][j]))
Mx=i;
swap(A[Mx],A[j]);
for(int i=1;i<=N;i++){
if(i==j)continue;
LD tmp=A[i][j]/A[j][j];
A[i][j]=0;
for(int k=j+1;k<=N+1;k++)
A[i][k]-=A[j][k]*tmp;
}
}
for(int i=1;i<=N;i++)
Ans[i]=A[i][N+1]/A[i][i];
}
int main(){
scanf("%d%d",&N,&M);
for(int i=1,x,y,z;i<=M;i++){
scanf("%d%d%d",&x,&y,&z);
P[x].push_back(y);
T[x].push_back(z);
if(x==y)continue;//自环.
P[y].push_back(x);
T[y].push_back(z);
}
for(int k=0;k<=30;k++){
for(int i=1;i<N;i++){
int size=P[i].size();
for(int j=0;j<size;j++){
int v=P[i][j];
int val=(T[i][j]&(1<<k));
if(val)A[i][v]+=1,A[i][N+1]+=1;
else A[i][v]-=1;
}
A[i][i]+=size;
}
A[N][N]=1.0;GX();
Ans0+=(1<<k)*Ans[1];
memset(A,0,sizeof(A));
}
printf("%.3Lf\n",Ans0);
}
/*
2 2
1 1 2
1 2 3
*/