首页 > 其他分享 >题解:【CF235D】Graph Game

题解:【CF235D】Graph Game

时间:2023-04-22 18:24:31浏览次数:46  
标签:return int 题解 void fa Game 63 Graph inline

题目链接

根据期望的线性性,一次操作使得接下来要递归处理 \(|G|\) 个点,将这些贡献分摊到 \(|G|\) 个点上,这样我们接下来只需要计算概率。

首先考虑如果是树怎么做。操作等价于随机一个排列,顺次删掉排列中的点,并求出删掉当前点之前其所处的连通块的大小。记当前 \(x\) 为点分治中心,点对 \((x,y)\) 的贡献为 \(y\) 在 \(x\) 的点分树内部,在 \(x \to y\) 的路径上 \(x\) 第一个被删除,这个事件的概率为 \(\dfrac{1}{dis_{i,j} + 1}\),其中 \(dis\) 表示两点间的距离。

把这个东西放在基环树上。如果点对 \((x,y)\) 在同一棵树中和上面情况相同,是平凡的。如果在不同子树中,意味着要跨过环。从环上走有两条路径,分别计算上两种走法的 \(\dfrac{1}{dis_{i,j} + 1}\) 并加起来。不过这样还会算重,容斥一下,再减去 \(x\) 和 \(y\) 到环上的距离加环上的总点数 分之一。

综上所述,我们需要预处理的东西有哪些点在环上面,哪些点在同一棵树中,同一棵树中的节点两两点对间的路径长度。然后枚举点对,如果在同一棵树中我们要求点对的 LCA,使用倍增求 LCA,总时间复杂度为 \(\mathcal O(n^2 \log n)\)。

#include<bits/stdc++.h>
#define ld long double 
#define ull unsigned long long
#define int long long
#define eb emplace_back
#define mp make_pair
using namespace std;
 
inline int read()
{
	int s=0,w=1; char c=getchar();
	while(!isdigit(c)) {if(c=='-') w=-1; c=getchar();}
	while(isdigit(c)) s=(s<<1)+(s<<3)+(c^48),c=getchar();
	return s*w;
}
inline void write(int x,char ch)
{
	if(x<0) x=-x,putchar('-');
	static char stk[25]; int top=0;
	do {stk[top++]=x%10+'0',x/=10;} while(x);
	while(top) putchar(stk[--top]);
	putchar(ch);
	return;
}
 
namespace MyTool
{
	static const int Mod=1e9+7;
	template<typename T> inline void Swp(T &a,T &b) {T t=a;a=b;b=t;}
	inline int  Max(int a,int b)   {return (b&((a-b)>>63))|(a&(~(a-b)>>63));}
	inline int  Min(int a,int b)   {return (a&((a-b)>>63))|(a&(~(a-b)>>63));}
	template<typename T> inline void cmax(T &a,T b) {a=a>b?a:b;}
	template<typename T> inline void cmin(T &a,T b) {a=a<b?a:b;}
	inline int  Abs(int a) {return (a^(a>>63))-(a>>63);}
	inline void Madd(int &a,int b) {a=a+b>Mod?a+b-Mod:a+b;}
	inline void Mdel(int &a,int b) {a=a-b<0?a-b+Mod:a-b;}
	inline void Mmul(int &a,int b) {a=1ll*a*b%Mod;}
	inline void Mmod(int &a) {a=(a%Mod+Mod)%Mod;}
	inline int  Cadd(int a,int b)  {return a+b>=Mod?a+b-Mod:a+b;}
	inline int  Cdel(int a,int b)  {return a-b<0?a-b+Mod:a-b;}
	inline int  Cmul(int a,int b)  {return a*b%Mod;}
	inline int  Cmod(int a)  {return (a%Mod+Mod)%Mod;}
	inline int  gcd(int a,int b)   {return b?gcd(b,a%b):a;}
	inline int  qpow(int a,int b)  {int res=1; while(b) {if(b&1) Mmul(res,a); Mmul(a,a); b>>=1;} return res;}
	inline int  qmul(int a,int b)  {int res=0; while(b) {if(b&1) Madd(res,a); Madd(a,a); b>>=1;} return res;}
	template<typename T> inline T pow(T x)    {return x*x;}
}
using namespace MyTool;
 
inline void file()
{
	freopen(".in","r",stdin);
	freopen(".out","w",stdout);
	return;
}
 
bool Mbe;
 
namespace LgxTpre
{
	static const int MAX=3010;
	static const int inf=2147483647;
	static const int INF=4557430888798830399;
	static const int mod=998244353;
	static const int bas=131;
	
	int n,x,y;
	double ans;
	
	struct edge
	{
		int nex,to;
	}e[MAX<<1];
	int head[MAX],cnt;
	inline void add(int x,int y)
	{
		e[++cnt].nex=head[x],head[x]=cnt,e[cnt].to=y;
		return;
	}
	
	int loop[MAX],deg[MAX],len,st;
	queue<int> q;
	inline void find_loop()
	{
		for(int i=1;i<=n;++i) if(deg[i]==1) q.push(i),loop[i]=1;
		while(!q.empty())
		{
			int now=q.front(); q.pop();
			for(int i=head[now];i;i=e[i].nex)
			{
				int to=e[i].to;
				if(--deg[to]==1) q.push(to),loop[to]=1;
			}
		}
		for(int i=1;i<=n;++i) loop[i]^=1,len+=loop[i],loop[i]==1?st=i:st=st;
		return;
	}
	
	int dep[MAX],col[MAX],fa[MAX][30],vis[MAX],num;
	void dfs(int now,int father,int id)
	{
		col[now]=id,fa[now][0]=father,dep[now]=dep[father]+1; 
		for(int i=1;i<=__lg(dep[now]);++i) fa[now][i]=fa[fa[now][i-1]][i-1];
		for(int i=head[now];i;i=e[i].nex)
		{
			int to=e[i].to;
			if(loop[to]||to==father) continue;
			dfs(to,now,id);
		}
		return;
	}
	inline int LCA(int x,int y)
	{
		if(dep[x]<dep[y]) Swp(x,y);
		while(dep[x]>dep[y]) x=fa[x][__lg(dep[x]-dep[y])];
		if(x==y) return x;
		for(int k=__lg(dep[x]);~k;--k) if(fa[x][k]!=fa[y][k]) x=fa[x][k],y=fa[y][k];
		return fa[x][0];
	}
	void find_tree(int now)
	{
		dfs(now,0,++num),vis[now]=1;
		for(int i=head[now];i;i=e[i].nex)
		{
			int to=e[i].to;
			if(!loop[to]||vis[to]) continue;
			find_tree(to);
		}
		return;
	}
	
	inline void mian()
	{
		n=read();
		for(int i=1;i<=n;++i) x=read()+1,y=read()+1,add(x,y),add(y,x),++deg[x],++deg[y];
		find_loop(),find_tree(st);
		for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) 
			if(col[i]==col[j])
				ans+=1.0/((double)(dep[i]+dep[j]-dep[LCA(i,j)]*2+1));
			else
			{
				double T=(double)(dep[i]+dep[j]);
				double L=(double)(fabs(col[i]-col[j])-1);
				double fL=(double)(len-L-2);
				ans+=1.0/(L+T)+1.0/(fL+T)-1.0/(L+fL+T);
			}
		printf("%.15lf\n",ans);
		return;
	}
}
 
bool Med;
 
signed main()
{
//	file();
	fprintf(stderr,"%.3lf MB\n",(&Med-&Mbe)/1048576.0);
	LgxTpre::mian();  
	cerr<<1e3*clock()/CLOCKS_PER_SEC<<" ms\n";
	return (0-0);
}

标签:return,int,题解,void,fa,Game,63,Graph,inline
From: https://www.cnblogs.com/LittleTwoawa/p/17343641.html

相关文章

  • 二叉树经典题解
    目录......
  • winform设置背景图闪屏问题解决
    直接将以下代码复制粘贴到出现闪屏的窗体中即可:#region解决添加背景图片时闪屏的问题protectedoverrideCreateParamsCreateParams{get{CreateParamscp=base.CreateParams;cp.Ex......
  • 暗的连锁 题解
    题目描述Dark是一个无向图,图中有\(n\)个结点和两类边,一类边被称为主要边,而另一类被称为附加边。Dark有\(n-1\)条主要边,并且Dark的任意两个结点之间都存在一条只由主要边构成的路径。另外,Dark还有\(m\)条附加边。你的任务是把Dark斩为不连通的两部分。一开始Dark......
  • ABC298E 题解
    前言题目传送门!更好的阅读体验?题解区的代码都好丑啊,嘲讽。思路对于这种概率题,正常人都能反应到这是dp。所以:\(dp_{t,i,j}\)表示:当前是第\(t\)回合,Tak在\(i\)位置,Aok在\(j\)位置,概率。如果这样设状态的话,转移方程就会非常一眼(刷表):\[dp_{t,\min(i+\texttt{st......
  • [P8766 [蓝桥杯 2021 国 AB] 异或三角]题解
    P8766[蓝桥杯2021国AB]异或三角题目描述分析题目中给出了三个限制首先我们不妨设\(a,b\ltc\),则而由于我们把\(c\)作为了最大值,原题需要有序对\((a,b,c)\)所以\(ans\ast3\)1.\(1\leqa,b,c\leqn\)2.\(a\oplusb\oplusc=0\)3.\(a+b\gtc\)而在枚举过程中,......
  • P1350 车的放置 题解
    一、题目描述:给你一个网格棋盘,a,b,c,d 表示了对应边长度,也就是对应格子数。例如,当a=b=c=d=2时,对应如下面这样一个棋盘:想要在这个棋盘上放 k棋子,也就是这 k 个棋子没有两个在同一行,也没有两个在同一列,问有多少种方案。数据保证 0......
  • [ARC138D] Differ by K bits 题解
    小清新构造题。首先\(K=1\)的情况是trival的,直接格雷码即可。对于\(K>1\),我们发现题目的约束相当于\(\operatorname{popcount}(P_i\oplusP_{(i+1)\bmod2^N})=K\),考虑\(P_i\)的差分序列\(D_i\),那么\(D_i\)一定是一个恰好有\(K\)位\(1\)的二进制数,记\(S=\{i\mid......
  • 团体程序设计天梯赛 L1-064 估值一亿的AI核心代码 题解
    思路L1-064估值一亿的AI核心代码题意有一点不太清晰的,就是原文中的'I',无论是否是单独的,都不能变为小写。如果是单独的'I'再被转化为'you'。这种模拟题就需要每个的分分清清楚楚的,不要都揉到一块儿,容易写错。具体还有些需要注意的在代码里注释着了。代码#include<iostream>......
  • Graph Travarsal All In One
    GraphtraversalAllInOne图遍历js/tsdemoshttps://hackbear.tv/gragph/https://hackbear.tv/gragph/1https://www.youtube.com/watch?v=BkszA-MvjXA?618(......
  • Android Studio Gradle Download 慢/卡问题解决
    build.gradlebuildscript{repositories{//jcenter()//jcenter(){url'http://jcenter.bintray.com/'}maven{url'http://maven.aliyun.com/nexus/content/groups/public/'}maven{url"https://jitpac......