https://codeforces.com/gym/102279/problem/G
思路
题目大意为给你两颗树,你可以把任何一个节点调整为根节点,调整只能改变父子关系,不能改变点与点的连接关系。通过调整后若第一棵树的高度大于第二棵树,则输出"GGEZ",否则输出"FF"。
找树的直径。先从任意一个节点开始找到离该节点最远的一个节点,再从最远的那个节点开始找,还是找离起始节点最远的节点,这两个节点是树中相距最远的两个节点。他们的距离便是树的直径。
题解
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+10;
vector<int> b2[maxn],hn[maxn];
struct node
{
int cnt,cot,res;
}mx1,mx2;
void dfs1(int u,int fa)
{
int flag=1;
for(int i=0;i<b2[u].size();i++)
{
if(b2[u][i]==fa)continue; //跳过父节点,保证完全往子树递归
mx1.cnt++;
dfs1(b2[u][i],u);
mx1.cnt--;
flag=0;
}
if(flag)
{
mx1.cnt++;
if(mx1.cnt>mx1.cot) mx1.cot=mx1.cnt,mx1.res=u;
mx1.cnt--; //回溯时忘减减了,d了一天的bug ,想锤死自己
return ;
}
}
void dfs2(int u,int fa)
{
int flag=1;
for(int i=0;i<hn[u].size();i++)
{
if(hn[u][i]==fa) continue;
mx2.cnt++;
dfs2(hn[u][i],u);
mx2.cnt--;
flag=0;
}
if(flag)
{
mx2.cnt++;
if(mx2.cnt>mx2.cot) mx2.cot=mx2.cnt,mx2.res=u;
mx2.cnt--; //回溯时忘减减了
return ;
}
}
int main()
{
int n,m,u,v;
int sum1,sum2;
cin>>n;
for(int i=1;i<=n-1;i++)
{
cin>>u>>v;
b2[u].push_back(v);
b2[v].push_back(u);
}
mx1.cot=mx1.res=mx1.cnt=0;
dfs1(u,0);
mx1.cnt=0;
mx1.cot=0;
dfs1(mx1.res,0);
sum1=mx1.cot;
cin>>m;
for(int i=1;i<=m-1;i++)
{
cin>>u>>v;
hn[u].push_back(v);
hn[v].push_back(u);
}
mx2.cot=mx2.res=mx2.cnt=0;
dfs2(u,0);
mx2.cnt=0;
mx2.cot=0;
dfs2(mx2.res,0);
if(mx2.cot>=3)sum2=(mx2.cot-1)/2+1; //当树只有两个节点时它的高度时2而非1
else sum2=mx2.cot;
if(sum1>sum2)cout<<"GGEZ"<<endl;
else cout<<"FF"<<endl;
}
许老师的代码
//G
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
vector<int> G[2][100500];
int h[200050];
int from,to;
int maxv;
void dfs(int v,int fa,int now,int t){
h[v] = now;
for(int i=0;i<G[t][v].size();i++){
int to = G[t][v][i];
if(fa == to) continue;
dfs(to,v,now+1,t);
}
return;
}
int main(){
int n;
cin>>n;
for(int i=0;i<n-1;i++){
int u,v;
scanf("%d%d",&u,&v);
G[0][u].push_back(v);
G[0][v].push_back(u);
}
dfs(1,-1,0,0);
for(int i=1;i<=n;i++){
if(maxv<h[i]){
maxv = h[i];
from = i;
}
}
dfs(from,-1,0,0);
for(int i=1;i<=n;i++){
if(maxv<h[i]){
maxv = h[i];
to = i;
}
}
int m;
cin >> m;
for(int i=0;i<m-1;i++){
int u,v;
scanf("%d%d",&u,&v);
G[1][u].push_back(v);
G[1][v].push_back(u);
}
dfs(1,-1,0,1);
int maxv2 = 0;
for(int i=1;i<=m;i++){
if(h[i]>maxv2){
from = i;
}
maxv2 = max(maxv2 , h[i]);
}
dfs(from,-1,0,1);
for(int i=1;i<=m;i++){
maxv2 = max(maxv2,h[i]);
}
maxv2 = (maxv2+1)/2;
if(maxv<=maxv2){
cout<<"FF";
}
else cout<<"GGEZ";
return 0;
}