魔法树 - 提答 - 点分治

本文探讨了点分树的概念及其在树形数据结构中的应用,重点讲解了如何通过重心分解来优化树的操作效率,包括如何寻找树的重心以及如何利用重心进行数据处理。文章还提供了详细的代码实现和数据生成方法,帮助读者深入理解并实践点分树和重心分解算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目大意:
现在有人用一下方法独立生成了T棵大小为n的树:
每次选择任意两点x和y,若二者不连通则连接x和y。
这个人将其中某些树求了一波点分树,每层重心多个取最小。
现在问你哪些是被操作过的。 T = 1000 , 60 ≤ n ≤ 1000 T=1000,60\le n\le1000 T=1000,60n1000
题解:
显然点分树重心也是原树重心,其次其每个儿子也应当是其子树的重心,以此类推……然后就过了,正确率近乎100%(其实10000,30都大部分时间是100的说)。(我还加了个链长的判断的说)。重心多个只要有任意一个ok就ok。
造数据:

#include<bits/stdc++.h>
#define N 1000100
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
struct edges{
	int to,pre;
}e[N<<1];int h[N],etop,sz[N],vis[N],dfc,lst[N],Lcnt,u[N],v[N],cnt;
inline int getn(int a,int b) { return rand()%(b-a+1)+a; }
inline int add_edge(int u,int v) { return e[++etop].to=v,e[etop].pre=h[u],h[u]=etop; }
int getsz(int x,int fa=0)
{
	lst[++Lcnt]=x,sz[x]=1;
	for(int i=h[x],y;i;i=e[i].pre)
		if((e[i].to^fa)&&!vis[y=e[i].to]) sz[x]+=getsz(y,x);
	return sz[x];
}
inline int getrt(int &x)
{
	for(int i=1,fsz=sz[x],t=fsz;i<=Lcnt;i++)
	{
		int y=lst[i],ysz=fsz-sz[y];
		for(int j=h[y];j;j=e[j].pre)
			if(!vis[e[j].to]&&sz[e[j].to]<sz[y])
				ysz=max(ysz,sz[e[j].to]);
		if((ysz<t)||(ysz==t&&y<x)) t=ysz,x=y;
	}
	return 0;
}
int solve(int x)
{
	Lcnt=0,getsz(x),getrt(x),vis[x]=1,dfc=0;
	for(int i=h[x],y,z;i;i=e[i].pre) if(!vis[y=e[i].to]) z=solve(y),cnt++,u[cnt]=x,v[cnt]=z;
	return x;
}
int fa[N];
inline int findf(int x)
{
	int fx=x,y;while(fx^fa[fx]) fx=fa[fx];
	while(x^fx) y=fa[x],fa[x]=fx,x=y;return fx;
}
FILE *fp=fopen("ylds.out","w");
inline int make_tree(int n)
{
	int cnt=0;
	for(int i=1;i<=n;i++) fa[i]=i;
	do{
		int x=getn(1,n),y=getn(1,n);
		if(findf(x)!=findf(y)) cnt++,u[cnt]=x,v[cnt]=y,fa[fa[x]]=fa[y];
	}while(cnt<n-1);
	for(int i=1;i<=cnt;i++) fprintf(fp,"%d %d\n",u[i],v[i]);fprintf(fp,"\n");
	return 0;
}
int main()
{
	freopen("tree.in","w",stdout);
	int T=10000,n=60;printf("%d %d\n",T,n);
	srand((unsigned int)time(0));
	while(T--)
	{
		int isyes=getn(0,1);
		isyes=(isyes>0);
		printf("%d\n",isyes);
		make_tree(n);
		if(!isyes)
		{
			for(int i=1;i<n;i++)
				printf("%d %d\n",u[i],v[i]);
			continue;
		}
		memset(h,0,sizeof(int)*(n+1)),etop=0;
		for(int i=1;i<n;i++) add_edge(u[i],v[i]),add_edge(v[i],u[i]);
		cnt=0,memset(vis,0,sizeof(int)*(n+1));solve(1);
		for(int i=1;i<n;i++) printf("%d %d\n",u[i],v[i]);
	}
	return 0;
}

跑数据:

#include<bits/stdc++.h>
#define gc getchar()
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define N 1000000
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
inline int inn()
{
	int x,ch;while((ch=gc)<'0'||ch>'9');
	x=ch^'0';while((ch=gc)>='0'&&ch<='9')
		x=(x<<1)+(x<<3)+(ch^'0');return x;
}
struct edges{
	int to,pre;
}e[N<<1];int h[N],etop,sz[N];
inline int add_edge(int u,int v) { return e[++etop].to=v,e[etop].pre=h[u],h[u]=etop; }
inline int getsz(int x,int fa=0)
{
	sz[x]=1;
	for(int i=h[x],y;i;i=e[i].pre)
		if((y=e[i].to)^fa) sz[x]+=getsz(y,x);
	return sz[x];
}
int rtcnt,rt[10];
inline int getrt(int n)
{
	int x=1,xsz=0;rtcnt=1;rt[1]=x;
	for(int i=h[x];i;i=e[i].pre) xsz=max(xsz,sz[e[i].to]);
	for(int y=2;y<=n;y++)
	{
		int ysz=n-sz[y];
		for(int i=h[y],z;i;i=e[i].pre)
			if(sz[z=e[i].to]<sz[y]) ysz=max(ysz,sz[z]);
		if(ysz==xsz) rt[rtcnt=2]=y;
		else if(ysz<xsz) xsz=ysz,rt[rtcnt=1]=y;
	}
	return 0;
}
inline int getdpt(int x,int fa=0)
{
	//debug(x)ln;
	int d=0;
	for(int i=h[x],y;i;i=e[i].pre)
		if((y=e[i].to)^fa) d=max(d,getdpt(y,x));
	//debug(x)sp,debug(d+1)ln;
	return d+1;
}
inline int check_sz(int n)
{
	for(int x=1;x<=n;x++)
	{
		for(int i=h[x],y;i;i=e[i].pre)
			if(sz[y=e[i].to]<sz[x]) { if(sz[y]*2>sz[x]) return 0; }
	}
	return 1;
}
#define MyTest
int main()
{
#ifdef MyTest
	system("mkdt.exe");
#endif
	freopen("tree.in","r",stdin);
	freopen("tree.out","w",stdout);
	int T=inn(),n=inn(),cnt=0;
	for(int qwqqwq=1;qwqqwq<=T;qwqqwq++)
	{
#ifdef MyTest
		int isyes=inn();
#else
		int isyes=0;
#endif
		int u,v;
		memset(h,0,sizeof(int)*(n+1)),etop=0;
		rep(i,1,n-1) u=inn(),v=inn(),add_edge(u,v),add_edge(v,u);
		int ns=n,QwQ1=0;while(ns>1) ns/=2,QwQ1++;QwQ1++;
		getsz(1),getrt(n);int ok=0;
		for(int i=1;i<=rtcnt;i++)
		{
			int x=rt[i],can=1;
			getsz(x);
			if(getdpt(x)>QwQ1) can=0;
			if(!check_sz(n)) can=0;
			if(can) ok=1;
		}
		if(ok) printf("Yes\n"),cnt+=(isyes==1);
		else printf("No\n"),cnt+=(isyes==0);
	}
#ifdef MyTest
	fprintf(stderr,"There are %d Test cases and %d answers are correct.\n",T,cnt);
	fprintf(stderr,"So %.3lf%% of them is correct, and you've got %.3lf points.\n",100.0*cnt/T,100*max(2.0*cnt/T-1,0.0)*max(2.0*cnt/T-1,0.0));
#endif
	return 0;
}
内容概要:本文详细介绍了如何使用Matlab对地表水源热泵系统进行建模,并采用粒子群算法来优化每小时的制冷量和制热量。首先,文章解释了地表水源热泵的工作原理及其重要性,随后展示了如何设定基本参数并构建热泵机组的基础模型。接着,文章深入探讨了粒子群算法的具体实现步骤,包括参数设置、粒子初始化、适应度评估以及粒子位置和速度的更新规则。为了确保优化的有效性和实用性,文中还讨论了如何处理实际应用中的约束条件,如设备的最大能力和制冷/制热模式之间的互斥关系。此外,作者分享了一些实用技巧,例如引入混合优化方法以加快收敛速度,以及在目标函数中加入额外的惩罚项来减少不必要的模式切换。最终,通过对优化结果的可视化分析,验证了所出的方法能够显著降低能耗并高系统的运行效率。 适用人群:从事暖通空调系统设计、优化及相关领域的工程师和技术人员,尤其是那些希望深入了解地表水源热泵系统特性和优化方法的专业人士。 使用场景及目标:适用于需要对地表水源热泵系统进行精确建模和优化的情景,旨在找到既满足建筑负荷需求又能使机组运行在最高效率点的制冷/制热量组合。主要目标是在保证室内舒适度的前下,最大限度地节约能源并延长设备使用寿命。 其他说明:文中供的Matlab代码片段可以帮助读者更好地理解和复现整个建模和优化过程。同时,作者强调了在实际工程项目中灵活调整相关参数的重要性,以便获得更好的优化效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值