POJ 2631 Roads in the North
Roads in the North
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 3239   Accepted: 1615

Description

Building and maintaining roads among communities in the far North is an expensive business. With this in mind, the roads are build such that there is only one route from a village to a village that does not pass through some other village twice. 
Given is an area in the far North comprising a number of villages and roads among them such that any village can be reached by road from any other village. Your job is to find the road distance between the two most remote villages in the area. 

The area has up to 10,000 villages connected by road segments. The villages are numbered from 1. 

Input

Input to the problem is a sequence of lines, each containing three positive integers: the number of a village, the number of a different village, and the length of the road segment connecting the villages in kilometers. All road segments are two-way.

Output

You are to output a single integer: the road distance between the two most remote villages in the area.

Sample Input

5 1 6
1 4 5
6 3 9
2 6 8
6 1 7

Sample Output

22

Source

Problem Idea

 【题意】
     题目理解:鉴于北部最远的一个地区,其中包括一些村庄和道路,这样任何村庄都可以从任何其他村庄通过公路到达。
       你的工作是找出 该地区两个最偏远村庄之间的道路距离.
  题意简述:有一个树结构, 给你树的所有边(u,v,cost), 表示u和v两点间有一条距离为cost的边. 然后问你该树上最远的两个点的距离是多少?(即树的直径)
 【类型】
  求树的直径
 【分析】
  求树的直径算法,模板题,入门。
     【算法的核心思想】
  两次BFS,第一次对树中的任意节点u进行BFS,找到最长路的一个端点
         第二次对该点进行BFS,找到最长路的另一个端点,则两点之间的路径即为树的直径。
  其中,以下程序是用邻接表来表示树结构的。Edge是用来表示每条边的结构。BFS返回从s结点能走到的最远的点的编号
       Head[i]=j 表示在邻接表中,通过头节点i,找到与其相连接的边j,这些边在邻接表的每一行都组成了一条链表, 其中第j条边是这条链的头一个元素, 接着通过j可以找到剩余的(与i连接的)边.

 【输入输出要求】

   输入输出要求,用中文复述一下:
  给出最远村庄节点对,及其他们之间的距离的值。
  <村庄A> <村庄B> <距离>
  【注意】
   1、本题输入输出没有指定具体的节点数目n和边数m,所以需要用while(scanf("%d%d%d",&u,&v,&cost)==3)来判断输入是否结束
   2、代码提交要用C++,不能用G++,否则会运行超时。

Source Code

#include <iostream>
#include <queue>
#include <cstring>
#include <cstdio>
//从任意一点u出发搜到的最远的点一定是s、t中的一点,然后在从这个最远点开始搜,就可以搜到另一个最长路的端点
// 即用两遍广搜就可以找出树的最长路
using namespace std;
const int nmax=10000+5;
const int mmax=1000000+5;

struct Edge{
    int to,cost,next;//边尾部,边距离,指向下条边
    Edge(){}
    Edge(int to,int cost,int next):to(to),cost(cost),next(next){}
}edges[mmax];
int cnt=0;//边总数
int head[nmax];//邻接表的头结点

void AddEdge(int u,int v,int cost){//在邻接表中添加两条有向边
    edges[cnt]=Edge(v,cost,head[u]);
    head[u]=cnt++;
    edges[cnt]=Edge(u,cost,head[v]);
    head[v]=cnt++;
}

int dist[nmax];//当前的最远距离,dist[i]表示当前点到点i的距离;

int BFS(int s){//BFS返回从s出发能到达的最远点编号
    int maxdist=0;//记录最远距离
    int id=s;//记录最远节点,初始化为s
    queue<int> q;
    memset(dist,-1, sizeof(dist));
    dist[s]=0;
    q.push(s);

    while(!q.empty()){
        int u=q.front();
        q.pop();//出队头元素
        if(dist[u]>maxdist){
            maxdist=dist[id=u];//更新最远距离,同时记录最远点的id
        }
        //main中需要初始化// memset(head,-1, sizeof(head));
        for(int i=head[u];i!=-1;i=edges[i].next){//如果u节点还未被访问,则访问u节点;之后再访问edges[i].next节点

            Edge &e=edges[i];
            if(dist[e.to]==-1){
                dist[e.to]=dist[u]+e.cost;//如若未被访问,则更新当前的最远距离
                q.push(e.to);
            }
        }//end of for
    }//end of while
    return id;
}
int main() {
        cnt=0;
        memset(head,-1, sizeof(head));
        int u,v,cost;
        while(scanf("%d%d%d",&u,&v,&cost)==3){
            AddEdge(u,v,cost);
        }
        //getchar();
        printf("%d\n",dist[BFS(BFS(u))]);//第一次对任意节点u进行BFS,找到最长路的端点
                                         //第二次对该点进行BFS,找到最长路的另一个端点,则两点之间的路径即为树的直径
    return 0;
}