2020 BIT冬训-图&&DFS&&BFS L - Three Paths on a Tree CodeForces - 1294F(树的直径)
问题描述
给出一个含有n个点的树。
你从树上钦定三个不同的点a,b,c,如果一个边在其中两个点的简单路径上,它就是“好边”。你需要求出最多有多少个"好边",并且输出任一一种选定a,b,c的方案。
输入格式
第一行一个整数n。
接下来n-1行每行两个数a,b表示一条边的两个端点。
输出格式
第一行一个数表示好边最多有多少个。
第二行是三个数表示一种钦定a,b,c使得好边个数最多的方案。
样例输入
8
1 2
2 3
3 4
4 5
4 6
3 7
3 8
样例输出
5
1 8 6
数据范围
3<=n<=2e5
Note
样例对应的图片如下 :
本题的思路是先两次DFS求出树的直径。(树的直径的求法和定义见该链接)
再BFS求出离直径最远的那个点。(如果没有分支那么就是直径)
AC代码如下:
#include <algorithm> #include<iostream> #include<cstdio> #include<cstring> #include<vector> #include<queue> #define MAXN 200005 using namespace std; int n,temp1,temp2,spos,epos,dis[MAXN],vis[MAXN],cnt,tcnt,tmax,tpos; vector<int>g[MAXN]; vector<int>d; queue<int>q; int find(int s,int e){ if(s==e&&tcnt==cnt){//如果找到了终点且是最长路径,则返回1 return 1; } vis[s]=1; for(int i=0;i<g[s].size();i++){ if(!vis[g[s][i]]){ d.push_back(g[s][i]); tcnt++; if(find(g[s][i],e)) return 1; tcnt--; d.erase(d.end()-1); } } return 0; } void dfs(int s,int &e){ if(cnt<dis[s]){ cnt=dis[s]; e=s; } vis[s]=1; for(int i=0;i<g[s].size();i++){ if(!vis[g[s][i]]){ dis[g[s][i]]=dis[s]+1; dfs(g[s][i],e); } } } int main(){ scanf("%d",&n); for(int i=0;i<n-1;i++){ scanf("%d%d",&temp1,&temp2); g[temp1].push_back(temp2); g[temp2].push_back(temp1); } memset(dis,0,sizeof(dis)); memset(vis,0,sizeof(vis)); cnt=0; dfs(1,spos);//第一次dfs,找到离1最远的点并赋给spos memset(dis,0,sizeof(dis)); memset(vis,0,sizeof(vis)); cnt=0; dfs(spos,epos);//第二次dfs,找到离spos最远的点并赋给epos。两次dfs后的spos和epos就是最短路径 memset(vis,0,sizeof(vis)); d.push_back(spos); find(spos,epos);//找出直径上的点,并存入d tcnt=0; if(cnt==n-1){//如果所有点都在直径上,那么答案为直径长度,直径的起点终点和中间任意一点 printf("%d\n%d %d %d\n",cnt,spos,epos,d[1]); }else{//如果有分支,即有点不在直径上,则取一个距直径最远的点加入即可。 memset(vis,0,sizeof(vis)); memset(dis,0,sizeof(dis)); for(int i=0;i<d.size();i++){//bfs求各点到直径的距离 vis[d[i]]=1; q.push(d[i]); } tmax=0; while(!q.empty()){ int u =q.front(); q.pop(); for(int i=0;i<g[u].size();i++){ if(!vis[g[u][i]]){ dis[g[u][i]]=max(dis[g[u][i]],dis[u]+1); if(tmax<dis[g[u][i]]){//更新最远距离和点的下标 tmax=dis[g[u][i]]; tpos=g[u][i]; } vis[g[u][i]]=1; q.push(g[u][i]); } } } printf("%d\n%d %d %d\n",cnt+tmax,spos,epos,tpos); } }

浙公网安备 33010602011771号