• UVA 1390 Interconnect


    https://vjudge.net/problem/UVA-1390

    题意:

    给出n个点m条边的无向图,

    每次随机加一条非自环的边,(加完后可出现重边),

    添加每条边的概率是相等的

    求使图连通的期望添边次数

    只关心图的连通状况,即连通块的个数和大小

    所以可以用{a1,a2,a3……an} 表示状态(n个连通块,每个连通块大小为ai)

    添加一条边后有两种可能

    1、状态不变

    2、状态变为 {a1,……ai+aj,……a_n-1}

    将状态哈希

    dp[i]表示哈希后为i的状态 添边至连通的期望次数

    dp[i]= dp[i]*p + dp[k1]*p1 + dp[k2]*p2  + …… + dp[km]*pm

    其中p表示状态不变的概率,p1=Σ C(ai,2)/ C(n,2)

    pi表示装移到ki这种状态的概率 ,pi= (ai*aj) / C(n,2)

    上述式子移项得状态转移方程:dp[i]=(dp[k1]*p1 + dp[k2]*p2  + …… + dp[km]*pm)/(1-p)

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    const int mod=100019;
    int n,m;
    int fa[31],siz[31];
    struct sta
    {
        int x[30];
        bool flag;
        double val;
        void clear() { memset(x,0,sizeof(x)); }
        void sort() { std::sort(x,x+30); }
        int hashme()
        {
            int v=0;
            for(int i=29,b=1;i&&x[i];i--)
            {
                v+=x[i]*b;
                v%=mod;
                b*=30;
                b%=mod;
            }
            return v;
        }
        bool operator == (sta b)
        {
            for(int i=0;i<30;i++)
                if(x[i]!=b.x[i]) return false;
            return true;
        }
        bool operator != (sta b)
        {
            return *this == b ? false : true;
        }
    }st,hash[mod];
    int find(int i) { return fa[i]==i ? i : fa[i]=find(fa[i]); }
    double gethash(sta st)
    {
        int x=st.hashme();
        while(hash[x].flag && hash[x]!=st)
            if(++x==mod) x=0;
        return hash[x]==st ? hash[x].val : -1;
    }
    double inhash(sta st)
    {
        int x=st.hashme();
        while(hash[x].flag) 
            if(++x==mod) x=0;
        hash[x]=st; hash[x].flag=true;
    }
    double dp(sta st)
    {
        if(st.hashme()==n) return 0;
        double x=gethash(st);
        if(x!=-1) return x;
        double tmp=0,ans=0;
        for(int i=0;i<30;i++)
            tmp+=st.x[i]*(st.x[i]-1)/2;
        for(int i=0;i<30;i++)
            for(int j=i+1;j<30;j++)
            {
                if(!st.x[i] || !st.x[j]) continue;
                sta tmp=st;
                tmp.x[i]+=tmp.x[j];
                tmp.x[j]=0;
                tmp.sort();
                ans+=st.x[i]*st.x[j]*dp(tmp);
            }
        ans/=n*(n-1)/2;
        ans++;
        ans/=1-tmp/(n*(n-1)/2);
        st.val=ans;
        inhash(st);
        return ans;
    }
    int main()
    {
        int u,v;
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            for(int i=0;i<mod;++i) hash[i].flag=false;
            for(int i=1;i<=n;i++) fa[i]=i;
            while(m--)
            {
                scanf("%d%d",&u,&v);
                fa[find(u)]=find(v);
            }
            st.clear();
            memset(siz,0,sizeof(siz));
            for(int i=1;i<=n;i++) siz[find(i)]++;
            int tot=0;
            for(int i=1;i<=n;i++) 
                if(siz[i]) st.x[tot++]=siz[i];
            st.sort();
            printf("%.7lf
    ",dp(st));
        }
    }
  • 相关阅读:
    多线程
    socket
    十一、内置模块
    十、模块与包
    Javaweb学习笔记11 JDBC
    Javaweb学习笔记10 4种范围对象
    Javaweb学习笔记9 application
    Javaweb学习笔记8 session与cookie区别
    Javaweb学习笔记7 session
    Javaweb学习笔记6 jsp页面元素
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/7465234.html
Copyright © 2020-2023  润新知