题解:
比较简单的一道题
显然我们只需要知道每个联通块的大小就可以了
然后发现x1+xn=30 其中xi<=xi+1的状态只有5000
所以直接记忆化搜索就可以了
emm原来map还可以映射vector这些我还以为要自己写
代码(比较暴力):
#include <bits/stdc++.h> using namespace std; #define me(x) memset(x,0,sizeof(x)) #define me1(x) memset(x,1,sizeof(x)) #define rint register int #define IL inline #define rep(i,h,t) for (rint i=h;i<=t;i++) #define dep(i,t,h) for (rint i=t;i>=h;i--) const int N=2e3+10; const double ee=1.0000000000; int n,m,l,num,cnt,head[N],kk; vector<int> ve; map<vector<int>,double> M; bool f[N]; struct re{ int a,b; }a[N*2]; void arr(int x,int y) { a[++l].a=head[x]; a[l].b=y; head[x]=l; } void dfs1(int x) { cnt++; f[x]=0; int u=head[x]; while (u) { int v=a[u].b; if (f[v]) dfs1(v); u=a[u].a; } } IL bool cmp(int x,int y) { return x<y; } double dfs(int x) { if (ve[0]==n) { return(0); } if (M[ve]) return(M[ve]); double ans=0; int now=kk; int now2=now; int l=ve.size()-1; rep(i,0,l) rep(j,i+1,l) { vector<int>ve1; rep(k,0,l) if (k!=i&&k!=j) ve1.push_back(ve[k]); ve1.push_back(ve[i]+ve[j]); sort(ve1.begin(),ve1.end(),cmp); ve1.swap(ve); ans+=ee*ve1[i]*ve1[j]*(dfs(x+1)+1)/now; ve.swap(ve1); now2-=ve[i]*ve[j]; } ans+=ee*now2/now; ans/=ee-(ee*now2/now); M[ve]=ans; return(ans); } int main() { freopen("1.in","r",stdin); freopen("1.out","w",stdout); ios::sync_with_stdio(false); cin>>n>>m; kk=n*(n-1)/2; rep(i,1,m) { int x,y; cin>>x>>y; arr(x,y); arr(y,x); } me1(f); rep(i,1,n) if (f[i]) { cnt=0; dfs1(i); ve.push_back(cnt); } sort(ve.begin(),ve.end(),cmp); printf("%.6f",dfs(m)); return 0; }