题目描述
分析
首先可以证明,肯定存在合法的方案
那么就有一个 (60) 分的 (n imes 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
",g[now][0],now);
for(int i=1;i<g[now].size();i+=2){
printf("%d %d
",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
",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
",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
");
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
");
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
",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
",gg[now][0],now);
for(int i=1;i<gg[now].size();i+=2){
printf("%d %d
",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
",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
",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
");
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
",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
");
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
",sta[i].id,sta[i+1].id);
}
} else {
printf("%d %d
",sta[k].id,sta[1].id);
for(int i=2;i<k;i+=2){
printf("%d %d
",sta[i].id,sta[i+1].id);
}
}
}
return 0;
}