GMOJ 6838. 【2020.10.31提高组模拟】小j的组合
作者:互联网
GMOJ 6838. 【2020.10.31提高组模拟】小j的组合
题目描述
题解
这应该是这场比赛最水的一题,但我没切。
做法很简单,可以发现,进行一次操作,相当于是可以将某一个点多经过一次,感性理解。
然后找出直径,其他的点最终都要回到直径上,\(dfs\)统计答案即可。
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 300
using namespace std;
int n,x,y,i,g,q[N],tot,dis[N],xp,yp,mx,ans1[N],ans2[N],bz[N],num,f[N],id[N];
struct edge{
int to,next;
}e[N];
void insert(int x,int y){
tot++;
e[tot].to=y;
e[tot].next=q[x];
q[x]=tot;
}
void dfs(int x,int father){
int i,y;
f[x]=dis[x];id[x]=x;
for (i=q[x];i;i=e[i].next){
y=e[i].to;
if (y!=father){
dis[y]=dis[x]+1;
dfs(y,x);
if (f[y]>f[x]){
id[x]=y;
f[x]=f[y];
}
}
}
}
void dfs1(int x,int pl){
int i,j,y,sp=0;
bz[x]=1;
ans2[++ans2[0]]=x;
if (id[x]==x) return;
if (pl==0){
for (i=q[x];i;i=e[i].next){
y=e[i].to;
if (bz[y]==0&&id[x]!=y){
dfs1(y,1);
ans1[++ans1[0]]=x;
ans2[++ans2[0]]=n+ans1[0];
}
}
dfs1(id[x],0);
}
else{
for (i=q[x];i;i=e[i].next){
y=e[i].to;
if (bz[y]==0){
dfs1(y,1);
ans1[++ans1[0]]=x;
ans2[++ans2[0]]=n+ans1[0];
}
}
}
}
int main(){
freopen("combo.in","r",stdin);
freopen("combo.out","w",stdout);
scanf("%d",&n);
for (i=1;i<n;i++)
scanf("%d%d",&x,&y),insert(x,y),insert(y,x);
dfs(1,0);
for (i=1;i<=n;i++) if (dis[i]>mx) mx=dis[i],xp=i;
memset(dis,0,sizeof(dis));
memset(f,0,sizeof(f));
dfs(xp,0);
mx=0;
for (i=1;i<=n;i++) if (dis[i]>mx) mx=dis[i],yp=i;
mx++;g=n-mx;
printf("%d\n",g);
dfs1(xp,0);
for (i=1;i<=g;i++)
printf("%d ",ans1[i]);
printf("\n");
for (i=1;i<=n+g;i++)
printf("%d ",ans2[i]);
printf("\n");
return 0;
}
标签:int,ans1,31,6838,id,++,2020.10,ans2,dis 来源: https://www.cnblogs.com/Mohogany/p/13908812.html