XOR]および[BZOJ2337パス(ガウスの消去法)

トピックリンク

不注意な

所与\(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

*/

おすすめ

転載: www.cnblogs.com/ftotl/p/11856686.html