BZOJ1417: Pku3156 Interconnect

1417: Pku3156 Interconnect

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 271  Solved: 136
[Submit][Status][Discuss]

Description

给出无向图G(V, E). 每次操作任意加一条非自环的边(u, v), 每条边的选择是等概率的. 问使得G连通的期望操作次数. (|V| <= 30, |E| <= 1000)

Input

第一行两个整数N,M 1<=N<=30 0<=M<=1000 接下来M行,每行两个整数X,Y表示两者之间已修好一条道路. 两点之间可以不止修了一条路,也有可能M条路已使N个点成为一个整体.

Output

输出一个小数,表示新修道路条数的期望值,保留六位小数.

Sample Input

4 2
1 2
3 4

Sample Output

1.500000

HINT

 

Source

题解:我们考虑已存在边对建边是没有影响的,但是对于使图联通是有影响的,所以我们就可以利用这一点进行状态转移

#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));
}
View Code

 

posted @ 2016-08-21 22:12  ACist  阅读(252)  评论(0编辑  收藏  举报