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表示状态不变的概率,p=Σ 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\n",dp(st));
    }
}

 

posted @ 2017-09-01 22:01  TRTTG  阅读(412)  评论(0编辑  收藏  举报