POJ - 1985 Cow Marathon 奶牛马拉松 计算树的直径

来源:互联网 发布:推荐几个淘宝男装店铺 编辑:程序博客网 时间:2024/05/29 16:00

【问题描述】
农夫约翰有N个农场,标号为1到N。M条不同的垂直或水平的道路连接着农场,道路的长度不超过1000。这些农场的分布就像下面的地图一样,图中农场用F1..F7表示:

每个农场最多能在东西南北四个方向连接4个不同的农场。此外,农场只处在道路的两端。道路不会交叉且每个农场间有且仅有一条路径。但是约翰丢了农场的地图,他只得从电脑的备份信息中修复了。每一条道路信息描述如下:

从农场23往南经距离10到达农场17
从农场1往东经距离7到达农场17
……

最近美国过度肥胖非常普遍,农夫约翰为了让他的奶牛多做运动,举办了奶牛马拉松。马拉松路线要尽量长,请帮助约翰寻找两个最远的农场间的距离。

【输入格式】
第1行两个整数N和M。
第2到第M+1行:每行包括4个分开的整数:F1,F2,L,D分别描述两个农场的编号,道路的长度,F1到F2的方向N,E,S,W。

【输出格式】
一个整数,表示最远两个农场的距离。

【输入样例】

7 61 6 13 E6 3 9 E3 5 6 S4 1 3 N2 4 20 W4 7 2 S

【输出样例】

51

【样例解释】
最长的马拉松路线通过4,1,6,3到5;总长为:20+3+12+9+7=32。

【数据范围】
1<=N,M<=40000

思路:由题意的每两个农场有且只有一条道路,可知有N-1条边连接成连通图,即为一棵树。
求树上最远的路径,即为求树的直径。

计算树的直径的算法:
任选一点为树的根进行BFS或DFS,找到距离根结点最远的点,然后从该点再进行一次BFS或DFS,找到距该点最远的点,两点的距离即为树的直径。

代码:

#include<cstdio>#include<queue>#include<cstring>#include<vector>#include<algorithm>#define maxn 40005using namespace std;int n,m;int dist[maxn];bool vis[maxn];vector<int>g[maxn],w[maxn];void init(){    scanf("%d%d",&n,&m);    int x,y,c;    char ch[5];    for(int i=1;i<n;i++)    {        scanf("%d%d%d%s",&x,&y,&c,ch);        g[x].push_back(y);        g[y].push_back(x);        w[x].push_back(c);        w[y].push_back(c);    }}void BFS(int i){    queue<int>q;    memset(vis,0,sizeof(vis));    q.push(i);    vis[i]=1;    dist[i]=0;    while(!q.empty())    {        int i=q.front(); q.pop();        for(int k=0;k<g[i].size();k++)        {            int j=g[i][k];            int c=w[i][k];            if(vis[j]) continue;            dist[j]=dist[i]+c;            q.push(j);            vis[j]=1;        }    }}void solve(){    BFS(1);    int a=1;    for(int i=2;i<=n;i++)    {        if(dist[a]<dist[i]) a=i;    }    BFS(a);    int b=1;    for(int i=2;i<=n;i++)    {        if(dist[b]<dist[i]) b=i;    }    printf("%d\n",dist[b]);}int main(){    //freopen("in.txt","r",stdin);    init();    solve();    return 0;}
0 0
原创粉丝点击