1. 程式人生 > >魔法樹 - 提答 - 點分治

魔法樹 - 提答 - 點分治

題目大意:
現在有人用一下方法獨立生成了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;
}