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)); } }