给出无向图G(V, E). 每次操作任意加一条非自环的边(u, v), 每条边的选择是等概率的. 问使得G连通的期望操作次数. (|V| <= 30, |E| <= 1000)
标签:
给出无向图G(V, E). 每次操作任意加一条非自环的边(u, v), 每条边的选择是等概率的. 问使得G连通的期望操作次数. (|V| <= 30, |E| <= 1000)
第一行两个整数N,M 1<=N<=30 0<=M<=1000 接下来M行,每行两个整数X,Y表示两者之间已修好一条道路. 两点之间可以不止修了一条路,也有可能M条路已使N个点成为一个整体.
输出一个小数,表示新修道路条数的期望值,保留六位小数.
题解:我们考虑已存在边对建边是没有影响的,但是对于使图联通是有影响的,所以我们就可以利用这一点进行状态转移
#include<iostream> #include<algorithm> #include<cstring> #include<cstdio> #include<cmath> #include<map> #include<vector> #define ll long long #define vec vector<int> using namespace std; map <vec ,double> q; vec ve; int fa[35],size[35],all; int n,m; int read() { int x=0,f=1; char ch; while (ch=getchar(),ch<‘0‘||ch>‘9‘) if (ch==‘-‘) f=-1; while (x=x*10+ch-‘0‘,ch=getchar(),ch>=‘0‘&&ch<=‘9‘); return x*f; } int find(int x) { if (fa[x]!=x) fa[x]=find(fa[x]); return fa[x]; } void init() { n=read(); m=read(); for (int i=1; i<=n; i++) fa[i]=i,size[i]=1; for (int i=1; i<=m; i++) { int u=read(),v=read(); int q=find(u),p=find(v); if (q!=p) fa[q]=p,size[p]+=size[q]; } for (int i=1; i<=n; i++) if (fa[i]==i) ve.push_back(size[i]); sort(ve.begin(),ve.end()); all=n*(n-1)/2; } double solve(vec ve) { if (q.count(ve)) return q[ve]; if (ve.size()==1) return q[ve]=0; int sz=ve.size(); int p=0; for (int i=0; i<sz; i++) p+=ve[i]*(ve[i]-1)/2; double ans=1.0*all/(all-p); for (int i=0; i<sz; i++) { for (int j=0; j<i; j++) { vec v=ve; v[j]+=v[i]; swap(v[i],v[sz-1]); v.pop_back(); sort(v.begin(),v.end()); ans+=1.0*ve[i]*ve[j]/(all-p)*solve(v); } } return q[ve]=ans; } int main() { init(); printf("%0.6lf\n",solve(ve)); }
BZOJ1417: Pku3156 Interconnect
标签:
原文地址:http://www.cnblogs.com/HQHQ/p/5793779.html