晚间测试2 凉宫春日的消失

题目描述





分析

首先可以证明,肯定存在合法的方案
那么就有一个 \(60\) 分的 \(n\times q\) 的做法
对于每一次询问,我们对整棵树进行一次 \(dfs\)
如果当前子树中有奇数个点被选择,那么我们保留一个点,把剩下的点两两配对
如果有偶数个点被选择,那么我们直接把它们都配对即可
对与另外的 \(15\) 分链的情况,我们直接按照深度大小排序即可
对于 \(100\%\) 的数据

代码(75分)

#include<cstdio>
#include<cstring>
#include<vector>
#include<cmath>
#include<algorithm>
inline int read(){
	int x=0,fh=1;
	char ch=getchar();
	while(ch<'0' || ch>'9'){
		if(ch=='-') fh=-1;
		ch=getchar();
	}
	while(ch>='0' && ch<='9'){
		x=(x<<1)+(x<<3)+(ch^48);
		ch=getchar();
	}
	return x*fh;
}
const int maxn=1e6+5,maxk=305;
int head[maxn],tot=1,n;
struct asd{
	int to,next;
}b[maxn];
void ad(int aa,int bb){
	b[tot].to=bb;
	b[tot].next=head[aa];
	head[aa]=tot++;
}
std::vector<int> g[maxk];
bool vis[maxk];
void dfs(int now,int fa){
	for(int i=head[now];i!=-1;i=b[i].next){
		int u=b[i].to;
		if(u==fa) continue;
		dfs(u,now);
		if(g[u].size()==1){
			g[now].push_back(g[u][0]);
			g[u].clear();
		}
	}
	if(g[now].size()%2==1){
		if(vis[now]){
			printf("%d %d\n",g[now][0],now);
			for(int i=1;i<g[now].size();i+=2){
				printf("%d %d\n",g[now][i],g[now][i+1]);
			}
			g[now].clear();
		} else {
			int cs=g[now][0];
			for(int i=1;i<g[now].size();i+=2){
				printf("%d %d\n",g[now][i],g[now][i+1]);
			}
			g[now].clear();
			g[now].push_back(cs);
		}
	} else {
		for(int i=0;i<g[now].size();i+=2){
			printf("%d %d\n",g[now][i],g[now][i+1]);
		}
		g[now].clear();
		if(vis[now]) g[now].push_back(now);
	}
}
void solve1(){
	int k,aa;
	while(1){
		k=read();
		if(k==0) break;
		memset(vis,0,sizeof(vis));
		for(int i=1;i<=n;i++){
			g[i].clear();
		}
		printf("Yes\n");
		for(int i=1;i<=k;i++){
			aa=read();
			vis[aa]=1;
		}
		dfs(1,0);
	}
}
int dep[maxn],maxdep,zsd;
void dfs2(int now,int fa){
	dep[now]=dep[fa]+1;
	if(dep[now]>maxdep){
		maxdep=dep[now];
		zsd=now;
	}
	for(int i=head[now];i!=-1;i=b[i].next){
		int u=b[i].to;
		if(u==fa) continue;
		dfs2(u,now);
	}
}
struct jl{
	int val,id;
	jl(){}
	jl(int aa,int bb){
		val=aa,id=bb;
	}
}sta[maxn];
bool cmp(jl aa,jl bb){
	return aa.val>bb.val;
}
int top=0;
void solve2(){
	int k,aa;
	while(1){
		k=read(),top=0;
		if(k==0) break;
		printf("Yes\n");
		for(int i=1;i<=k;i++){
			aa=read();
			sta[++top]=jl(dep[aa],aa);
		}
		std::sort(sta+1,sta+1+top,cmp);
		for(int i=1;i<=top;i+=2){
			printf("%d %d\n",sta[i].id,sta[i+1].id);
		}
	}
}
std::vector<int> gg[maxn];
bool viss[maxn];
void dfs3(int now,int fa){
	for(int i=head[now];i!=-1;i=b[i].next){
		int u=b[i].to;
		if(u==fa) continue;
		dfs3(u,now);
		if(gg[u].size()==1){
			gg[now].push_back(gg[u][0]);
			gg[u].clear();
		}
	}
	if(gg[now].size()%2==1){
		if(viss[now]){
			printf("%d %d\n",gg[now][0],now);
			for(int i=1;i<gg[now].size();i+=2){
				printf("%d %d\n",gg[now][i],gg[now][i+1]);
			}
			gg[now].clear();
		} else {
			int cs=gg[now][0];
			for(int i=1;i<gg[now].size();i+=2){
				printf("%d %d\n",gg[now][i],gg[now][i+1]);
			}
			gg[now].clear();
			gg[now].push_back(cs);
		}
	} else {
		for(int i=0;i<gg[now].size();i+=2){
			printf("%d %d\n",gg[now][i],gg[now][i+1]);
		}
		gg[now].clear();
		if(viss[now]) gg[now].push_back(now);
	}
}
void solve3(){
	int k,aa;
	int js=0;
	while(1){
		k=read(),top=0;
		js++;
		if(k==0) break;
		printf("Yes\n");
		if(js==1){
			for(int i=1;i<=k;i++){
				aa=read();
				viss[aa]=1;
			}
			dfs3(1,0);
		} else {
			for(int i=1;i<=k;i++){
				aa=read();
				sta[++top]=jl(dep[aa],aa);
			}
			std::sort(sta+1,sta+1+top,cmp);
			for(int i=1;i<=top;i+=2){
				printf("%d %d\n",sta[i].id,sta[i+1].id);
			}
		}
	}
}
int main(){
	freopen("kieru.in","r",stdin);
	freopen("kieru.out","w",stdout);
	memset(head,-1,sizeof(head));
	n=read();
	int aa,bb;
	for(int i=1;i<n;i++){
		aa=read(),bb=read();
		ad(aa,bb);
		ad(bb,aa);
	}
	dfs2(1,0);
	maxdep=0;
	dfs2(zsd,0);
	if(n<=300){
		solve1();
	} else if(maxdep==n){
		solve2();
	} else {
		solve3();
	}
	return 0;
}

代码(100分)

#include<cstdio>
#include<cstring>
#include<vector>
#include<cmath>
#include<algorithm>
inline int read(){
	int x=0,fh=1;
	char ch=getchar();
	while(ch<'0' || ch>'9'){
		if(ch=='-') fh=-1;
		ch=getchar();
	}
	while(ch>='0' && ch<='9'){
		x=(x<<1)+(x<<3)+(ch^48);
		ch=getchar();
	}
	return x*fh;
}
const int maxn=1e6+5,maxk=305;
int head[maxn],tot=1,n;
struct asd{
	int to,next;
}b[maxn];
void ad(int aa,int bb){
	b[tot].to=bb;
	b[tot].next=head[aa];
	head[aa]=tot++;
}
int siz[maxn],son[maxn],dep[maxn],f[maxn];
void dfs(int now,int fa){
	f[now]=fa;
	dep[now]=dep[fa]+1;
	siz[now]=1;
	for(int i=head[now];i!=-1;i=b[i].next){
		int u=b[i].to;
		if(u==fa) continue;
		dfs(u,now);
		siz[now]+=siz[u];
		if(son[now]==0 || siz[u]>siz[son[now]]){
			son[now]=u;
		}
	}
}
int tp[maxn],dfn[maxn],dfnc;
void dfs2(int now,int top){
	dfn[now]=++dfnc;
	tp[now]=top;
	if(son[now]) dfs2(son[now],top);
	for(int i=head[now];i!=-1;i=b[i].next){
		int u=b[i].to;
		if(u==f[now] || u==son[now]) continue;
		dfs2(u,u);
	}
}
struct jl{
	int val,id;
	jl(){}
	jl(int aa,int bb){
		val=aa,id=bb;
	}
}sta[maxn];
bool cmp(jl aa,jl bb){
	return aa.val<bb.val;
}
int get_LCA(int u,int v){
	while(tp[u]!=tp[v]){
		if(dep[tp[u]]<dep[tp[v]]) std::swap(u,v);
		u=f[tp[u]];
	}
	if(dep[u]<dep[v]) std::swap(u,v);
	return v;
}
int jsjl(int u,int v){
	return dep[u]+dep[v]-2*dep[get_LCA(u,v)];
}
int main(){
	freopen("kieru.in","r",stdin);
	freopen("kieru.out","w",stdout);
	memset(head,-1,sizeof(head));
	n=read();
	int k,aa,bb;
	for(int i=1;i<n;i++){
		aa=read(),bb=read();
		ad(aa,bb);
		ad(bb,aa);
	}
	dfs(1,0);
	dfs2(1,1);
	while(1){
		k=read();
		if(k==0) break;
		printf("Yes\n");
		for(int i=1;i<=k;i++){
			aa=read();
			sta[i]=jl(dfn[aa],aa);
		}
		std::sort(sta+1,sta+1+k,cmp);
		int ans=0;
		for(int i=1;i<=k;i+=2){
			ans+=jsjl(sta[i].id,sta[i+1].id);
		}
		if(ans<=n-1){
			for(int i=1;i<=k;i+=2){
				printf("%d %d\n",sta[i].id,sta[i+1].id);
			}
		} else {
			printf("%d %d\n",sta[k].id,sta[1].id);
			for(int i=2;i<k;i+=2){
				printf("%d %d\n",sta[i].id,sta[i+1].id);
			}
		}
	}
	return 0;
}
posted @ 2020-10-05 16:42  liuchanglc  阅读(118)  评论(0编辑  收藏  举报