week11求树的直径

week11:求树的直径;
随机选点,搜索到距离该点最远的一点,然后从该点出发获得最远点,两点间距即为直径;正常思路
然后看了眼大佬的代码。real服。空间换时间。
每当加入一条边:就当是两条边;
to数组存边号对应的终点,hd数组存起点对应的边号,nx数组存该起点对应的另一条边;
核心代码非常诡异:

int cl(int u,int p){
    int a=0,b=0,t;
    for(int i=hd[u];i;i=nx[i])//u的每一个方向
        if(to[i]!=p)//如果没有走回起点
        if((t=cl(to[i],u)+1)>b)//迭代取得u经过i边的最远。(即u为折点)
        if((b=t)>a)
        t=a,a=b,b=t;//之前t>b>a;现在a>b>t;
    if((b+=a)>ans)ans=b;//该点一边最远a一边最远b;
    return a;//经过u的最远;
}

这个代码倒是严格按提示来的,a保留了u开始最长,b保留了u开始次长;返回a+b;就是逻辑很难顺下来啊。

看了下poj1849的报告
1849的题是这样:n个点,n-1条有权边,从S点出发的两辆车 遍历完所有节点走过的路最短。
由题可知不成环。那么就只有两种情况:
1.起点在直径上,那么直接求树的直径就好
2.起点不在直径上:最长链只被遍历一遍,其余都是两遍
显然1是2的特殊情形。
用bfs吧 因为dfs经常用。
所以要S干嘛。。。觉得我随机找一点开始太浪费时间,从起点开始?
用数组模拟搞过了。
不过bfs的正规套路是queue啊。
步步为营 一视同仁 无解方止

queue<Point> q;
q.push(start);
Point next;
while(!q.empty())//队列不为空继续扩展
{
    Point tmp=q.front();
    q.pop();
    for(int i = 0; i < 8; ++i)
    {
        next.row = tmp.row + directR[i];
        next.col = tmp..col + directC[i];
        if(inmap(next) && !visited[next.row][next.col])//inmap判断是否在地图内
        {
            next.moves = tmp.moves + 1;
            if(next.row == end.row && next.col == end.col)//如果是终点
                return next.moves;
            q.push(next);//入列
            visited[next.row][next.col] = true;//标志为走过
        }
    }
}

    原文作者:vaisy
    原文地址: https://www.jianshu.com/p/3ea7f9a26550
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞