题目链接——http://net.hpuacm.cf/contests
题意:
这个世界是由无数的透明房间组成,每间屋子都有一个或者若干个门,这些门将这些房间相连,保证任意两个房间只有一条路径可以相互到达(保证这个世界的结构是一个树形结构)。Philo与A分别处于两个透明的房间内。Philo想要远离 A ,现在请你帮助他。
对于每个房间都有一个编号,两个相邻房间距离是1,已知Philo在x房间,A在y房间,Philo每次移动都会远离A,A会同时选择远离Philo,期间他们的距离只会不断增大。他们停止的条件都是到达不能再往前走的房间,即只有一扇门的房间。
题面大家已经看的差不多了,相信也理解了题意: 给一棵树, 求经过x和y两点的树上最长路径的长度。
输入
第一行一个整数T,表示测试组数. ( 0< T <= 100)
接下来的每组数据:
一行三个整数 n,x,y , n 表示这个世界房间的个数, x 和 y 即题意 (x != y ,0< n < 1e5).
接下来的n-1行,每行两个整数 a和 b 表示 a 房间与 b房间 之间可以互相到达( 0 <= a , b < n).
输出
每组数据一行,输出一个整数表示最长路径的长度.
HINT : 来自热心学长的提示 :为了降低难度,我们明确告诉大家这这个题的解法很多,不一定要用树形dp
输入样例 1
1 4 0 1 0 2 1 2 2 3
输出样例 1
2
相信经过题目提示,大家可以想到这是一个树的dfs,一共经过两次搜索,第一次搜x,y的距离,第二次分别搜索x,y节点到各自子叶末端的最大距离,然后把这三者相加就是结果
代码;
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int vis[maxn];
int ans1,ans2,ans,sum;
int n,x,y;
int flag=0;
vector< pair<int,int> >oj[maxn];
void ini()
{
for(int i=0;i<=n;i++) oj[i].clear();
memset(vis,0,sizeof(vis));
sum=0;
ans=0;
ans1=0;
ans2=0;
flag=0;
}
void dfs(int v)
{
if(v==y)
{
flag=1;
return ;
}
else
{
pair<int,int> t;
for(int i=0;i<oj[v].size();i++)
{
t=oj[v][i];
if(vis[t.first]==1) continue;
vis[t.first]=1;
//sum=+=t.second;
sum += t.second;
dfs(t.first);
if(flag==1) return ;
sum -= t.second;
vis[t.first]=0;
}
}
}
void dfs2(int v,int e,int sum)
{
if(oj[v].size()==1&&oj[v][0].first==e) ans=max(ans,sum);//取最大值
else
{
pair<int,int> t;
for(int i=0;i<oj[v].size();i++)
{
t=oj[v][i];
if ( vis[ t.first ]==1) continue;
vis[ t.first ] = 1;
dfs2 ( t.first , v , sum + t.second );
vis[ t.first ] = 0;
}
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&n,&x,&y);
ini();
for(int i=1;i<=n-1;i++)
{
int a,b;
scanf("%d%d",&a,&b);
oj[a].push_back(make_pair(b,1));//用pair来保存该点的末尾结点和长度,尽管在这道题长度为1,但是掌握这个思路不失为一个好处
oj[b].push_back(make_pair(a,1));//无向图所以...
}
vis[x] = 1;//先把起始点标记已走,以免回来又搜到x点,导致时间浪费
dfs(x);//搜x,y的距离,因为两点只有一条路径,所以搜到的值就是最大值
dfs2(x,x,0);//搜x到末尾的最远距离
ans1 = ans;
ans = 0;
dfs2(y,y,0);
ans2 = ans;
cout<< sum + ans1 + ans2 << endl;
}
}