• 【BZOJ2337】XOR和路径(HNOI2011)-DP+概率期望+高斯消元


    测试地址:XOR和路径
    做法:本题需要用到DP+概率期望+高斯消元。
    首先,位运算有一个很好的性质,那就是每一位实际上是相互独立的,所以我们按照二进制位把边权拆开,那么我们现在只需要解决一个子问题即可:在一个边权只有01的图上,求从点1走到点n的期望异或和。
    我们可以令f(i)为从点i走到点n的期望异或和,我们发现这其实也是路径上异或和为1的概率,那么1f(i)自然就是异或和为0的概率,那么对于每个点我们有状态转移方程:
    f(i)=1deg(i)[w(i,j)=0f(j)+w(i,j)=1(1f(j))]
    那么我们把方程组列出来后,O(n3)解出所有未知数即可。注意我们已知f(n)=0,计算前要把所有已知条件都先带进去,然后就是自环和重边的处理,重边的话用前向星存图即可,主要是自环,要注意一个自环对一个点度数的贡献是1而不是2
    以下是本人代码:

    #include <bits/stdc++.h>
    using namespace std;
    int n,m,first[110]={0},tot=0;
    long double deg[110]={0},g[110][110];
    struct edge
    {
        int v,w,next;
    }e[20010];
    
    void insert(int a,int b,int w)
    {
        e[++tot].v=b;
        e[tot].w=w;
        e[tot].next=first[a];
        first[a]=tot;
    }
    
    void init()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
        {
            int a,b,w;
            scanf("%d%d%d",&a,&b,&w);
            insert(a,b,w);
            if (a!=b) insert(b,a,w);
            deg[a]+=1.0;
            if (a!=b) deg[b]+=1.0;
        }
    }
    
    void gauss(int n)
    {
        for(int i=1;i<=n;i++)
        {
            int mx=i;
            for(int j=i;j<=n;j++)
                if (fabs(g[j][i])>fabs(g[mx][i])) mx=j;
            for(int j=i;j<=n+1;j++)
                swap(g[i][j],g[mx][j]);
            for(int j=1;j<=n;j++)
                if (j!=i)
                {
                    for(int k=i+1;k<=n+1;k++)
                        g[j][k]-=g[j][i]*g[i][k]/g[i][i];
                    g[j][i]=0.0;
                }
        }
    }
    
    void work()
    {
        long double b=1.0,ans=0.0;
        for(int i=0;i<=30;i++,b*=2.0)
        {
            memset(g,0,sizeof(g));
            for(int j=1;j<n;j++)
            {
                for(int k=first[j];k;k=e[k].next)
                {
                    int v=e[k].v;
                    if (v!=n)
                    {
                        if ((e[k].w>>i)&1) g[j][v]+=1.0,g[j][n]+=1.0;
                        else g[j][v]-=1.0;
                    }
                    else if ((e[k].w>>i)&1) g[j][n]+=1.0;
                }
                for(int k=1;k<=n;k++)
                    g[j][k]/=deg[j];
                g[j][j]+=1.0;
            }
            gauss(n-1);
            ans+=g[1][n]*b/g[1][1];
        }
        printf("%.3Lf",ans);
    }
    
    int main()
    {
        init();
        work();
    
        return 0;
    }
  • 相关阅读:
    php实现上传图片保存到数据库的方法
    支付宝集成——如何在回调地址中使用自定义参数
    QQ音乐的各种相关API
    xampp默认mysql密码设置,修改mysql的默认空密码
    node.js 初体验
    php调用empty出现错误Can't use function return value in write context
    ecshop数据库操作函数
    ecshop中$user对象
    为什么我的联想打印机M7450F换完墨粉之后打印机显示请更换墨粉盒?这是我的墨盒第一次灌粉·、
    PHP中获取当前页面的完整URL
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793481.html
Copyright © 2020-2023  润新知