【树的直径】POJ 1985 Cow Marathon


 POJ 1985 Cow Marathon


Cow Marathon
题目链接->http://poj.org/problem?id=1985
Time Limit: 2000MS   Memory Limit: 30000K
Total Submissions: 5841   Accepted: 2826
Case Time Limit: 1000MS

Description

After hearing about the epidemic of obesity in the USA, Farmer John wants his cows to get more exercise, so he has committed to create a bovine marathon for his cows to run. The marathon route will include a pair of farms and a path comprised of a sequence of roads between them. Since FJ wants the cows to get as much exercise as possible he wants to find the two farms on his map that are the farthest apart from each other (distance being measured in terms of total length of road on the path between the two farms). Help him determine the distances between this farthest pair of farms. 

Input

* Lines 1.....: Same input format as "Navigation Nightmare".

Output

* Line 1: An integer giving the distance between the farthest pair of farms. 

Sample Input

7 6
1 6 13 E
6 3 9 E
3 5 7 S
4 1 3 N
2 4 20 W
4 7 2 S

Sample Output

52

Hint

The longest marathon runs from farm 2 via roads 4, 1, 6 and 3 to farm 5 and is of length 20+3+13+9+7=52. 

Source

USACO 2004 February

Problem Idea

 【题意】
     题目理解:农场主希望在他的地图上找到 距离彼此最远的两个农场(距离是根据两个农场之间的道路上的总长度来衡量的)。 帮助他确定这个 最远的一对农场之间的距离
  题意简述:有一个树结构, 给你树的所有边(u,v,cost), 表示u和v两点间有一条距离为cost的边. 然后问你该树上最远的两个点的距离是多少?(即树的直径)
 【类型】
  求树的直径
 【分析】
  求树的直径算法,模板题,入门。
     【算法的核心思想】
  两次BFS, 第一次对树中的任意节点u进行BFS,找到最长路的一个端点
         第二次对该点进行BFS,找到最长路的另一个端点,则两点之间的路径即为树的直径
该算法的相关证明-> 点击打开链接
  其中,以下程序是用邻接表来表示树结构的。Edge是用来表示每条边的结构。BFS返回从s结点能走到的最远的点的编号
       Head[i]=j 表示在邻接表中,通过头节点i,找到与其相连接的边j,这些边在邻接表的每一行都组成了一条链表, 其中第j条边是这条链的头一个元素, 接着通过j可以找到剩余的(与i连接的)边.

 【输入输出要求】

   输入输出要求,用中文复述一下:
  第一行包含农场的数量N 和农场之间的路径数量M,
  接下来的M行,给出最远农场对,及其他们之间的距离的值。
  <农场A> <农场B> <距离>

Source Code

#include 
#include 
#include 
#include 
//从任意一点u出发搜到的最远的点一定是s、t中的一点,然后在从这个最远点开始搜,就可以搜到另一个最长路的端点
// 即用两遍广搜就可以找出树的最长路
using namespace std;
const int nmax=50000+5;
const int mmax=100000+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 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() {
    int n,m;
    while(scanf("%d%d",&n,&m)==2){
        cnt=0;
        memset(head,-1, sizeof(head));
        int u,v,cost;
        char c;
        for(int i=1;i<=m;i++){
            scanf("%d%d%d %c",&u,&v,&cost,&c);
            AddEdge(u,v,cost);
        }
        //getchar();
        printf("%d\n",dist[BFS(BFS(u))]);//第一次对任意节点u进行BFS,找到最长路的端点
                                         //第二次对该点进行BFS,找到最长路的另一个端点,则两点之间的路径即为树的直径
    }
    return 0;
}

你可能感兴趣的:(机试)