题意:给一个图,有些点之间已经连边,现在给每对点之间加边的概率是相同的,问使得整个图连通,加边条数的期望是多少。

此题可以用概率DP+并查集+hash来做。

用dp(i,j,k...)表示当前的每个联通分量的点数分别是i,j,k...(连通分量的个数不固定)时,加边的期望。

这样以dp(i,j,k)为例分析状态转移的过程,dp(i,j,k)=p1*dp(i,j,k)+p2*dp(i+j,k)+p3*dp(i,j+k)+p4*dp(j,i+k)+1。

终止条件是dp(n)=0,因为此时图一定联通,所以期望是0。

这个式子是怎么来的呢?

p1*dp(i,j,k)表示增加了一条边之后原来的联通分量没有改变时的情况,p1表示选中这样的无用边的概率;p2*dp(i+j,k)表示增加了一条连结i和j这两个联通分量的边,p2表示选中i和j之间的边的概率。最后的1表示增加了一条边。

这里我们要计算选边概率。

首先有n*(n-1)/2条边。

如果选中了不改变图的联通分量的边,此时说明每次加的边都属于一个连通分量,所以一共有sum{(cnt(i)*cnt(i)-1)/2}(cnt(i)表示该联通分量内有cnt(i)个点)种选择情况。

如果选中了某条边连结了某两个联通分量i、j,这个时候一共有cnt(i)*cnt(j)种情况。

计算概率只需要除以边的总数即可。

计算连通分量可以用并查集。

因为这个题只看图的连通情况不在乎具体是哪个点,因此可以对每个联通分量的点数排序,使得每个状态唯一,这样可以得到很多重叠的子问题,整个问题就可以用记忆化搜索完成了。

很明显问题的状态比较复杂,直接下手很难处理也容易超时,所以用hash处理状态压缩判重。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#define MOD 100007
using namespace std;
int n,m;
struct State
{
    double val;
    ];
    bool vis;
    State()
    {
        memset(x,,sizeof(x));
        vis=false;
    }
    void clear()
    {
        memset(x,,sizeof(x));
        vis=false;
    }
    void mysort()
    {
        sort(x,x+);
    }
    int myhash() const
    {
        ;
        ,b=; i>=&&x[i]; --i)
        {
            res+=x[i]*b;
            res%=MOD;
            b*=;
            b%=MOD;
        }
        return res;
    }
    bool operator ==(State &t)const
    {
        ; i<; ++i) if(x[i]!=t.x[i]) return false;
        return true;
    }
    bool operator !=(State &t) const
    {
        return !(*this==t);
    }
};
State has[MOD+],st;
void inserthash(State &p)
{
    int v=p.myhash();
    while(has[v].vis)
        ;
    has[v]=p;
    has[v].vis=true;
}
double gethash(State &p)
{
    int v=p.myhash();
    while(has[v].vis&&has[v]!=p)
        ;
    ;
}
];
int find(int p)
{
    return p==father[p]?p:(father[p]=find(father[p]));
}
void init()
{
    ; i<=n; ++i) father[i]=i;
    st.clear();
}
double DP(State &s)
{
    ;
    double v=gethash(s);
    if(v!=-1.0) return v;
    ,sn=n*(n-)/2.0;;
    ; i>=&&s.x[i]; --i)
        q+=s.x[i]*(s.x[i]-)/2.0;
    double &res=s.val;
    res=;
    ; i>=&&s.x[i]; --i)
        ; j>=&&s.x[j]; --j)
        {
            double p=s.x[i]*s.x[j]/sn;
            State t;
            ; k>=; --k)
                if(k!=i&&k!=j) t.x[k]=s.x[k];
                else if(k==i)  t.x[k]=s.x[i]+s.x[j];
                ;
            t.mysort();
            res+=p*DP(t);
        }
    res=res/(-q/sn);
    inserthash(s);
    return res;
}
];
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        init();
        ; i<m; ++i)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            int fx=find(x),fy=find(y);
            if(fx!=fy) father[fx]=fy;
        }
        memset(cnt,,sizeof(cnt));
        ; i<=n; ++i)
            cnt[find(i)]++;
        ; i<=n; ++i)
            st.x[i-]=cnt[i];
        st.mysort();
        printf("%.6f\n",DP(st));
    }
    ;
}

学习了http://www.cnblogs.com/swm8023/archive/2012/09/21/2696593.html

POJ 3156 - Interconnect (概率DP+hash)的更多相关文章

  1. poj 1322 Chocolate (概率dp)

    ///有c种不同颜色的巧克力.一个个的取.当发现有同样的颜色的就吃掉.去了n个后.到最后还剩m个的概率 ///dp[i][j]表示取了i个还剩j个的概率 ///当m+n为奇时,概率为0 # inclu ...

  2. POJ 3071 Football(概率DP)

    题目链接 不1Y都对不住看过那么多年的球.dp[i][j]表示i队进入第j轮的概率,此题用0-1<<n表示非常方便. #include <cstdio> #include &l ...

  3. Scout YYF I POJ - 3744(概率dp)

    Description YYF is a couragous scout. Now he is on a dangerous mission which is to penetrate into th ...

  4. POJ - 2151 (概率dp)

    题意:有T个队伍,有M道题,要求每个队至少有一道题,并且有队伍至少过N道题的概率. 这个题解主要讲一下,后面的,至少有一道题解决和至少一道题至N-1道题解决,到底怎么算的,其实,很简单,就是母函数. ...

  5. poj 3071 Football (概率DP水题)

    G - Football Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit ...

  6. POJ 1202 Family 概率,DP,高精 难度:2

    http://poj.org/problem?id=1202 难度集中在输出格式上,因为输出格式所以是高精度 递推式: 血缘肯定只有从双亲传到儿子的,所以,设f,m为双亲,son为儿子,p[i][j] ...

  7. poj 3071 Football(概率dp)

    id=3071">http://poj.org/problem? id=3071 大致题意:有2^n个足球队分成n组打比赛.给出一个矩阵a[][],a[i][j]表示i队赢得j队的概率 ...

  8. 【POJ】2151:Check the difficulty of problems【概率DP】

    Check the difficulty of problems Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 8903   ...

  9. POJ 2096 Collecting Bugs (概率DP,求期望)

    Ivan is fond of collecting. Unlike other people who collect post stamps, coins or other material stu ...

随机推荐

  1. Spring表达式语言 之 5.3 SpEL语法(拾肆)

    5.3  SpEL语法 5.3.1  基本表达式 一.字面量表达式: SpEL支持的字面量包括:字符串.数字类型(int.long.float.double).布尔类型.null类型. 类型 示例 字 ...

  2. Qt之属性系统

    简述 Qt提供一个类似于其它编译器供应商提供的复杂属性系统(Property System).然而,作为一个编译器和平台无关的库,Qt不能够依赖于那些非标准的编译器特性,比如:__property或者 ...

  3. Anagrams [LeetCode]

    Given an array of strings, return all groups of strings that are anagrams. Note: All inputs will be ...

  4. png-24在ie6中的几种透明方法

    转载 http://www.cnblogs.com/jikey/archive/2013/03/13/2957168.html 由于游戏类官网在页面背景和装饰人物的设计上追求画丽且与游戏风格想匹配,这 ...

  5. iOS的常见文件及程序的启动原理

    一. iOS中常见文件 (一). Xcode6之前 创建项目,默认可以看见一个存放框架的文件夹 info文件以工程文件名开头,如:第一个项目-Info.plist 项目中默认有一个PCH文件 (二). ...

  6. 分享一个快速的Json(反)序列化开源项目 Jil

    我们不缺少JSON的序列化库,但我们缺少一个性能非常好的库,这对于网站来说非常重要.今天我发现了Jil. 他是开源的代码: https://github.com/kevin-montrose/Jil ...

  7. 细谈HTML5

    回顾过了html接下来我们就来看看HTML5吧! HTML5手机应用的最大优势就是可以在网页上直接调试和修改.原先应用的开发人员可能需要花费非常大的力气才能达到HTML5的效果,不断地重复编码.调试和 ...

  8. 转载css层级优先级。

    解读CSS样式优先级(修改门户自定义样式必读) 一.什么是CSS优先级?所谓CSS优先级,即是指CSS样式在浏览器中被解析的先后顺序.当同一个元素(或内容)被多个CSS选择符选中时,就要按照优先权取舍 ...

  9. css样式书写的问题

    经常遇到前端的朋友问及css样式书写的问题,结合自己实际的工作,自己总结了整理了一下,给大家分享: 一.顺序问题:显示属性-位置属性-元素自身属性-文本属性-其他属性 1.显示属性:z-index.d ...

  10. mac 找文件

    如何找到 etc 方法1: ! D# D! s2 F" f 七度苹果电脑软件1.打开Finder,按快键盘 Command + Shift + G,即可调出 前往文件夹 ,也可以左上角 找到 ...