gmoj 6838. [2020.10.31 Improve group simulation] The combination of small j

topic

https://gmoj.net/senior/#main/show/6838

answer

This question seemed strange, so I ignored it during the competition.

Consider that a point is split several times in the final graph, and it is found that the number of splits is equal to the number of times it passes -1. Taking the starting point as the root, the path taken is to walk around a lot of sub-trees and return, and then choose a son to go down and not come back. The same goes for this son.

How can we make as many points as possible that do not return (obviously when a point returns to its father, its father must split once)? This is equivalent to choosing the longest simple path on the tree, the diameter .

Therefore, this question only needs to find the diameter, take one of its end points as the root, and then for each point on the diameter, first walk its non-diameter son's subtree and return, and then go along the diameter Go down.

CODE

#include<cstdio>
using namespace std;
#define M 205
#define N 105
int f[N][2],son[N][2],fir[N],to[M],nex[M],p[100005],now[N],pre[N],len,node,s;
bool b[N];
inline void inc(int x,int y)
{
    
    
	to[++s]=y,nex[s]=fir[x],fir[x]=s;
	to[++s]=x,nex[s]=fir[y],fir[y]=s;
}
void getd(int k,int fa)
{
    
    
	for(int i=fir[k];i;i=nex[i]) if(to[i]!=fa)
	{
    
    
		getd(to[i],k);
		if(f[to[i]][0]+1>f[k][0])
			f[k][1]=f[k][0],son[k][1]=son[k][0],
			f[k][0]=f[to[i]][0]+1,son[k][0]=to[i];
		else if(f[to[i]][0]+1>f[k][1])
			f[k][1]=f[to[i]][0]+1,son[k][1]=to[i];
	}
	if(f[k][0]+f[k][1]>len) len=f[k][0]+f[k][1],node=k;
}
void dfs(int k,int fa)
{
    
    
	p[++p[0]]=k;
	for(int i=fir[k];i;i=nex[i]) if(to[i]!=fa&&to[i]!=pre[k])
		dfs(to[i],k),p[++p[0]]=k;
	if(pre[k]) dfs(pre[k],k);
}
int main()
{
    
    
	freopen("combo.in","r",stdin);
	freopen("combo.out","w",stdout);
	int root,n,x,y,cnt;
	scanf("%d",&n),cnt=n;
	for(int i=1;i<n;++i) scanf("%d%d",&x,&y),inc(x,y);
	getd(1,0),root=node,b[root]=1;
	while(son[root][0]) pre[son[root][0]]=root,root=son[root][0],b[root]=1;
	if(son[node][1])
	{
    
    
		pre[node]=x=son[node][1],b[x]=1;
		while(son[x][0]) x=pre[x]=son[x][0],b[x]=1;
	}
	dfs(root,0);
	printf("%d\n",p[0]-n);
	for(int i=1;i<=p[0];++i)
	{
    
    
		if(!now[p[i]]) now[p[i]]=p[i];
		else printf("%d ",now[p[i]]),p[i]=now[p[i]]=++cnt;
	}
	puts("");
	for(int i=1;i<=p[0];++i) printf("%d ",p[i]);
	puts("");
	return 0;
}

Guess you like

Origin blog.csdn.net/huangzihaoal/article/details/109408688