JD测试开发笔试题,修路。
题目提炼出来就是【找出两条路径的长度乘积最大,要保证这两条路径没有公共的点,如果找不到就输出0】,这是一道原题【Codeforces Beta Round #14 D - Two Paths】。
学习了很久终于明白了这道题怎么做的。
对于每条边,我们依次把这条边去掉的话,就可以把原图分割成了两棵树,然后就成了求这两棵树的最远两个节点的距离,然后把两棵树求出来的结果相乘,看能不能更新max_ans。
在求每棵树路径时,假如去掉的是[a,b]这条边,从a点走,他就不走b点,而是走除b点之外的另外的路,然后一直走到底,会得到一个值len1,然后a点走另一个方向(假如有路的话),走到底得到len2,找出最大的两条路,len1和len2。len1+len2就是a这边这棵树的最大的路径。然后再找出b那边的树的最大的路径长度。相乘。检查能否更新值。
然后接下来枚举下一条边。。。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int N = 206;
vector<int> G[N];
int maxlen;
int res;
int dfs(int a, int b)
{
int sum = 0;//两边的和,就是过a点的这条路的长度,这个函数就是为了找出最长的它
int len1 = 0;//其中从a出发最长的一部分
int len2 = 0;//从a出发的第2长的路径。len2+len1就是其中一条路径长
for(int i = 0; i < G[a].size(); ++i)
{
if(G[a][i] != b)//线段【a,b】,从a开始寻找最长的路,由于[a,b]这条路断开,所以不走b点
{
sum = max( dfs(G[a][i], a) , sum);//下一个点继续走下去
if(maxlen > len1)//更新最长的
{
len2 = len1;
len1 = maxlen;
}
else if(maxlen > len2)//或者是更新第2长的
{
len2 = maxlen;
}
}
}
maxlen = len1 + 1;//更新边长,一条路走到底后,返回一步,长度加1。然后用它来判断是否需要更新当前最长的一部分路
sum = max(sum, len1 + len2);
return sum;
}
int main()
{
int n;
cin >> n;
//把图构建好
for(int i = 1; i < n; ++i)
{
int a, b;
cin >> a >> b;
G[a].push_back(b);
G[b].push_back(a);
}
//枚举每条边
for(int i = 1; i <= n; ++i)
{
for(int j = 0; j < G[i].size(); ++j)
{
int l = dfs(i, G[i][j]);//从a点出发
int r = dfs(G[i][j], i);//从b点出发
res = max(res, l*r);
}
}
cout << res << endl;
return 0;
}