zoukankan      html  css  js  c++  java
  • 【CF235D】Graph Game

    题目

    题目链接:https://codeforces.com/problemset/problem/235/D
    求基环树随机点分治总遍历次数期望。
    基环树随机点分治步骤:

    1. 遍历当前分治区域所有点一次。
    2. 在当前分治区域随机选择一个点 (x)
    3. (x) 删掉,产生的所有连通块递归处理。

    (nleq 3000)

    思路

    考虑枚举两个点 (x,y)(y) 能给 (x) 的贡献,其实就是当 (x) 作为分治中心的时候,(y)(x) 连通的期望。
    如果在树上,设 (x,y) 两点之间有 (d) 个点,很显然 (x)(y) 连通当前仅当 (x)(x)(y) 的链上第一个被删除的点,它的概率也就是 (frac{1}{d})
    这道题给出的是一棵基环树,如果两个点之间的路径只有 (1) 条,那么贡献就和树上一样。如果两点之间的路径有两条,容斥一下,设两条路径各自的点数分别为 (d1,d2),两条路径的并集的点数为 (d3),那么这一组点的贡献就是 (frac{1}{d1}+frac{1}{d2}-frac{1}{d3})
    时间复杂度 (O(n^2))

    代码

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N=3010;
    int n,m,tot,head[N],id[N],siz[N],rk[N],top[N],deg[N],dep[N],a[N];
    double ans;
    
    struct edge
    {
    	int next,to;
    }e[N*2];
    
    void add(int from,int to)
    {
    	e[++tot]=(edge){head[from],to};
    	head[from]=tot;
    }
    
    void topsort()
    {
    	queue<int> q;
    	for (int i=1;i<=n;i++)
    		if (deg[i]==1) q.push(i);
    	while (q.size())
    	{
    		int u=q.front(); q.pop();
    		for (int i=head[u];~i;i=e[i].next)
    		{
    			int v=e[i].to;
    			deg[v]--;
    			if (deg[v]==1) q.push(v);
    		}
    	}
    }
    
    void dfs1(int x,int fa,int tp)
    {
    	top[x]=tp; dep[x]=dep[fa]+1;
    	id[x]=++tot; rk[tot]=x; siz[x]=1;
    	for (int i=head[x];~i;i=e[i].next)
    	{
    		int v=e[i].to;
    		if (v!=fa && deg[v]<=1)
    		{
    			dfs1(v,x,tp);
    			for (int j=id[x];j<id[x]+siz[x];j++)
    				for (int k=id[v];k<id[v]+siz[v];k++)
    					ans+=2.0/(dep[rk[j]]+dep[rk[k]]-2*dep[x]+1);
    			siz[x]+=siz[v];
    		}
    	}
    }
    
    void dfs2(int x,int fa,int tp)
    {
    	a[x]=++m;
    	for (int i=head[x];~i;i=e[i].next)
    	{
    		int v=e[i].to;
    		if (deg[v]>=2 && v!=fa && v!=tp)
    			return (void)(dfs2(v,x,tp));
    	}
    }
    
    int main()
    {
    	memset(head,-1,sizeof(head));
    	scanf("%d",&n);
    	for (int i=1,x,y;i<=n;i++)
    	{
    		scanf("%d%d",&x,&y);
    		x++; y++;
    		add(x,y); add(y,x);
    		deg[x]++; deg[y]++;
    	}
    	topsort();
    	tot=0;
    	for (int i=1;i<=n;i++)
    		if (deg[i]>=2) dfs1(i,0,i);
    	for (int i=1;i<=n;i++)
    		if (deg[i]>=2) { dfs2(i,0,i); break; }
    	for (int i=1;i<=n;i++)
    		for (int j=1;j<=n;j++)
    			if (top[i]!=top[j])
    			{
    				int d1=abs(a[top[i]]-a[top[j]])-1,d2=m-d1-2;
    				ans+=1.0/(dep[i]+dep[j]+d1)+1.0/(dep[i]+dep[j]+d2);
    				ans-=1.0/(dep[i]+dep[j]+m-2);
    			}
    	printf("%.12lf",ans+n);
    	return 0;
    }
    
  • 相关阅读:
    hdu 4710 Balls Rearrangement()
    hdu 4707 Pet(DFS水过)
    hdu 4706 Children's Day(模拟)
    hdu 4712 Hamming Distance(随机函数暴力)
    csu 1305 Substring (后缀数组)
    csu 1306 Manor(优先队列)
    csu 1312 榜单(模拟题)
    csu 1303 Decimal (数论题)
    网络爬虫
    Python处理微信利器——itchat
  • 原文地址:https://www.cnblogs.com/stoorz/p/15173257.html
Copyright © 2011-2022 走看看