• [HNOI 2011] XOR和路径


    [题目链接]

             https://www.lydsy.com/JudgeOnline/problem.php?id=2337

    [算法]

            直接进行计算显然是不可做的,我们考虑按位计算答案

            从低位向高位枚举,此时问题就转化为了 : 在一个联通无向图中,从1出发走到n,路径异或和为1的概率是多少

            用f[i]表示从i到n路径异或和为1的概率,有状态转移方程 :

            f[i] = sigma( f[j] / degree[i] ) ( w(i,j) = 0 ) + sigma( (1 - f[j]) / degree[i] ) ( w(i,j) = 1)

            由于图中可能存在自环和重边,我们无法确定枚举状态的顺序,因此,需要使用高斯消元

    [代码]

            

    #include<bits/stdc++.h>
    using namespace std;
    #define MAXN 110
    #define MAXM 10010
    #define MAXLOG 31
    
    int i,k,u,v,w,n,m,tot;
    int head[MAXN],degree[MAXN];
    double a[MAXN][MAXN];
    double ans;
    
    struct Edge
    {
            int to,w,nxt;
    } e[MAXM << 1];
    inline void addedge(int u,int v,int w)
    {
            tot++;
            e[tot] = (Edge){v,w,head[u]};
            head[u]    = tot;    
    }  
    inline void gauss()
    {
            int i,j,k,p;
            double rate;
            for (i = 1; i <= n; i++)
            {
                    p = i;
                    for (j = i + 1; j <= n; j++)
                    {
                            if (fabs(a[j][i]) > fabs(a[p][i]))
                                    p = j;         
                    }
                    for (j = 1; j <= n + 1; j++) swap(a[i][j],a[p][j]);
                    for (j = 1; j <= n; j++)
                    {
                            if (i == j) continue;
                            rate = a[j][i] / a[i][i];
                            for (k = i; k <= n + 1; k++) a[j][k] -= a[i][k] * rate;
                    }            
            } 
    }
    
    int main() 
    {
            
            scanf("%d%d",&n,&m);
            for (i = 1; i <= m; i++)
            {
                    scanf("%d%d%d",&u,&v,&w);
                    if (u ^ v)
                    {
                            addedge(u,v,w);
                            addedge(v,u,w);
                            degree[u]++; degree[v]++;
                    } else
                    {
                            addedge(u,v,w);
                            degree[u]++;
                    }
            }
            for (i = 0; i < MAXLOG; i++)
            {
                    for (u = 1; u <= n; u++)
                    {
                            for (v = 1; v <= n + 1; v++)
                            {
                                    a[u][v] = 0.0;
                            }
                    }
                    for (u = 1; u < n; u++)
                    {
                            for (k = head[u]; k; k = e[k].nxt)
                            {
                                    v = e[k].to;
                                    if (e[k].w & (1 << i))
                                    {
                                            a[u][v] -= 1.0 / degree[u];
                                            a[u][n + 1] -= 1.0 / degree[u];        
                                    } else a[u][v] += 1.0 / degree[u];
                            }    
                            a[u][u] -= 1.0;
                    }
                    a[n][n] = 1.0;
                    gauss();
                    ans += 1.0 * a[1][n + 1] / a[1][1] * (1 << i);
            }
            printf("%.3lf
    ",ans);
            
            return 0;
        
    }
  • 相关阅读:
    CSS
    html5
    XHTML
    HTML
    git 教程 --git revert 命令
    Git 教程 --git merge 命令
    git 教程 --git reset 命令
    git 教程 --git cherry-pick 命令
    git 教程 --git stash命令
    git 教程 --git diff功能
  • 原文地址:https://www.cnblogs.com/evenbao/p/9354996.html
Copyright © 2020-2023  润新知