本题跟https://www.luogu.com.cn/problem/P3478 类似,上面那道我A了,魔改了代码提交到这题就只剩20分,两题的思路都是一模一样的
#include<bits/stdc++.h>
using namespace std;
int n,k,a,b,jl,cnt=0,num=0,link[110000]={0},mark[110000]={0},head[310000]={0};
struct node{int to,next;}tree[210000];
queue<int> q,qt,qk;
void add(int u,int v){
cnt++;tree[cnt].to=v;tree[cnt].next=head[u];head[u]=cnt;
cnt++;tree[cnt].to=u;tree[cnt].next=head[v];head[v]=cnt;
}
void dfs(int x,int fa,int dis){
jl+=dis;
for(int i=head[x];i;i=tree[i].next){
if(tree[i].to==fa)continue;
dfs(tree[i].to,x,dis+1);
}//在找到开会地点后计算路径和,累计每个点到开会地点的距离
}
int main(){
cin>>n;
for(int i=1;i<n;i++){cin>>a>>b;add(a,b);link[a]++,link[b]++;}num=n;//link指与该点直接连接的点数
for(int i=1;i<=n;i++){if(link[i]==1)q.push(i),num--,mark[i]=1;}//找到所有的叶子结点
while(num>2){
while(!q.empty()){int temp=q.front();q.pop();
for(int i=head[temp];i;i=tree[i].next){link[tree[i].to]--;//在删掉一个叶节点后删掉与其相邻的点的连接数
if(link[tree[i].to]==1){qt.push(tree[i].to);num--;mark[tree[i].to]=1;}//如果成为叶节点就加入队列,等下一轮删掉
}
}q=qt;qt=qk;//qk是空队列,这样直接清空qt
}//一圈一圈的删点,删到只剩两个或一个,开会地点就在这里面。
for(int i=1;i<=n;i++)if(!mark[i]){cout<<i<<" ";dfs(i,0,0);break;}//找小的点
cout<<jl;
system("pause");return 0;
}