poj1985 Cow Marathon/树的直径模板

原题链接(http://poj.org/problem?id=1985)

题意

给定一棵n个点的树,m条边(m=n-1),每条边都有权值k,求树上距离最长的两个点的距离。(输入格式中的那个字母看起来没啥用)

数据范围:

\(n,k≤10000\)

思路

是树的直径模板题。
先随便找一个点为根,跑第一遍树上链形前缀和,找出离这个点距离最长的点,再以那个点为根,再跑一遍链形前缀和,这次求出离那个点距离最长的点一定就是最长距离了。

code:

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <queue>
using namespace std;
const int N=10005;
int b[N],cnt,n,m,head[N],total[N],total2[N],b2[N];
struct node{
    int u,v,w,next;
}ed[N];
void add_edge(int u,int v,int w)
{
    cnt++;
    ed[cnt].u=u;
    ed[cnt].v=v;
    ed[cnt].w=w;
    ed[cnt].next=head[u];
    head[u]=cnt;
}
void dfs(int xx)//第一次前缀和
{
    //前面没有赋自己的值,不要弄混两个前缀和 
    for(int i=head[xx];i!=0;i=ed[i].next)
    {
        int temp=ed[i].v;
        if(!b[temp])
        {
            b[temp]=1;
            total[temp]=ed[i].w+total[xx];
            dfs(temp);
        }
    }
}
void dfs2(int xx)//这是第二次前缀和
{
    for(int i=head[xx];i!=0;i=ed[i].next)
    {
        int temp=ed[i].v;
        if(!b2[temp])
        {
            b2[temp]=1;
            total2[temp]=ed[i].w+total2[xx];
            dfs2(temp);
        }
    }
}
int main()
{
    int m;
    cin>>n>>m;
    for(int i=1;i<=n-1;i++)
    {
        int x,y,k;
        char ch;
        cin>>x>>y>>k>>ch;
        add_edge(x,y,k);
        add_edge(y,x,k);
    }
    b[1]=1;
    dfs(1);
    int root,maxn=-1;
    for(int i=1;i<=n;i++)
    {
        if(total[i]>maxn)
        {
            maxn=total[i];
            root=i;
        }
    }
    b2[root]=1;
    dfs2(root);
    int root2,maxn2=-1;
    for(int i=1;i<=n;i++)
    {
        if(total2[i]>maxn2)
        {
            maxn2=total2[i];
            root2=i;
        }
    }
    cout<<maxn2;
    return 0;
}
上一篇:题解【洛谷P1522】牛的旅行 Cow Tours


下一篇:export和import的用法总结