魔法树 - 提答 - 点分治

题目大意:
现在有人用一下方法独立生成了T棵大小为n的树:
每次选择任意两点x和y,若二者不连通则连接x和y。
这个人将其中某些树求了一波点分树,每层重心多个取最小。
现在问你哪些是被操作过的。 T = 1000 , 60 n 1000 T=1000,60\le n\le1000
题解:
显然点分树重心也是原树重心,其次其每个儿子也应当是其子树的重心,以此类推……然后就过了,正确率近乎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;
}

猜你喜欢

转载自blog.csdn.net/Mys_C_K/article/details/82999216