Description

给定一张$n$个顶点$n$条边图,定义过程$solve(G),G$是一个连通块.

$1.totalCost=totalCost+|G|,|G|$表示图$G$中的节点个数.

$2.$在图$G$中随机选择一个节点$x$(每个点被选中的概率相等).

$3.$在图$G$中删除节点$x$.

$4.$图被分裂为几个连通块.

$5.$分治处理所有的子连通块$G',solve(G')$.

求$totalCost$的数学期望.

Input

第一行一个整数$n$,表示图中点的数量和边的数量.

接下来$n$行,每行两个空格隔开的整数$a_i,b_i$,表示一条$(a_i,b_i)$的无向边.
节点从$0$开始编号.

Output

仅一行输出一个实数,表示$totalCost$的数学期望.和标准答案绝对误差或相对误差在$10^{−6}$以内都被认为正确.

Sample Input


3 4
2 3
2 4
0 4
1 2

Sample Output

13.1666666666

HINT

$n\;\leq\;3000$

Solution

  • 树的情况

定义事件$P(A,B)$为在删除点$A$时,$B$点仍与$A$点连通的概率.

显然当一个事件发生时,答案$+1$,所以答案的期望值为所有事件的总和.

$P(A,B)=$在$AB$路径上的点数的倒数.

设$AB$路径上的点数为$n$.

  • 当连通块大小$=n$时,连通块为链$AB$.只有选取$A$时才会发生事件$P(A,B)$,概率为$\frac{1}{n}$.
  • 当连通块大小$\geq\;n$,为$x$时,选取的点有两种情况:
  1. 选取在$AB$链上,这时的概率为$\frac{n}{x}\times\frac{1}{n}$;
  2. 选取不在$AB$链上,概率为$\frac{x-n}{x}\times\frac{1}{n}$.
  • 相加为$\frac{1}{n}$.
    • 原题的情况
    • $AB$间的路径没通过环,结论同树.
    • $AB$间的路径经过了环,可以将路径上的点分成三部分:
      • 环外的点$x$,数量记为$X$.
      • 环上$A$到$B$顺时针的点$y$,数量记为$Y$.
      • 环上$B$到$A$顺时针的点$z$,数量记为$Z$.
    • 在选取$A$之前,$y,z$之间必须有一条不能被取,不能选取$x$.期望值为$\frac{1}{X+Y}+\frac{1}{X+Z}-\frac{1}{X+Y+Z}$.
    #include<cmath>
    #include<ctime>
    #include<queue>
    #include<stack>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #define N 3005 
    using namespace std;
    struct graph{
        int nxt,to;
    }e[N<<1];
    int g[N],t[N],d1[N],d2[N],n,cnt;
    bool ins[N];
    double ans;
    queue<int> q;
    inline int read(){
        int ret=0;char c=getchar();
        while(!isdigit(c))
            c=getchar();
        while(isdigit(c)){
            ret=(ret<<1)+(ret<<3)+c-'0';
            c=getchar();
        }
        return ret;
    }
    inline void addedge(int x,int y){
        e[++cnt].nxt=g[x];g[x]=cnt;e[cnt].to=y;
    }
    inline void toposort(){
        int u;
        for(int i=1;i<=n;++i)
            if(t[i]==1) q.push(i);
        while(!q.empty()){
            u=q.front();q.pop();++cnt;
            for(int i=g[u];i;i=e[i].nxt)
                if((--t[e[i].to]==1))
                    q.push(e[i].to);
        }
    }
    inline void dfs(int u){
        ins[u]=true;
        for(int i=g[u];i;i=e[i].nxt)
            if(!ins[e[i].to]){
                d2[e[i].to]=d2[u]+1;
                if(!d1[e[i].to]){
                    d1[e[i].to]=d1[u]+1;
                    ans+=1.0/(double)(d1[e[i].to]);
                }
                else ans+=1.0/(double)(d2[e[i].to])-2.0/(double)(d1[e[i].to]+d2[e[i].to]+cnt-2);
                dfs(e[i].to);
            }
        ins[u]=false;
    }
    inline void Aireen(){
        n=read();
        for(int i=1,j,k;i<=n;++i){
            j=read()+1;k=read()+1;
            addedge(j,k);addedge(k,j);
            ++t[j];++t[k];
        }
        cnt=0;toposort();cnt=n-cnt;
        for(int i=1;i<=n;++i){
            memset(d1,0,sizeof(d1));
            memset(d2,0,sizeof(d2));
            d1[i]=d2[i]=1;dfs(i);
        }
        printf("%.8lf\n",ans+n);
    }
    int main(){
        freopen("dac.in","r",stdin);
        freopen("dac.out","w",stdout);
        Aireen();
        fclose(stdin);
        fclose(stdout);
        return 0;
    }

    相关文章:

    • 2021-07-07
    • 2021-11-19
    • 2021-09-15
    • 2021-06-05
    • 2022-12-23
    • 2022-12-23
    • 2021-08-19
    • 2022-12-23
    猜你喜欢
    • 2022-12-23
    • 2022-12-23
    • 2022-01-30
    • 2022-12-23
    • 2022-12-23
    • 2022-12-23
    • 2021-07-05
    相关资源
    相似解决方案