首页 > 其他 > 详细

POJ 1849 Two(树的直径--树形DP)(好题)

时间:2015-03-15 12:28:02      阅读:498      评论:0      收藏:0      [点我收藏+]

大致题意:在某个点派出两个点去遍历所有的边,花费为边的权值,求最少的花费

思路:这题关键好在这个模型和最长路模型之间的转换,可以转换得到,所有边遍历了两遍的总花费减去最长路的花费就是本题的答案,要思考,而且答案和派出时的起点无关

求最长路两遍dfs或bfs即可,从任意点bfs一遍找到最长路的一个终点,再从这个终点bfs找到起点

//1032K	79MS	C++	1455B	
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;

const int N=1e5+100;
struct Edge
{
    int v,w;
    int next;
}es[N<<1];
int head[N];
int n,s;
bool vis[N];
int step[N];
int sum;
int bfs(int &st)
{
    int maxn=-1;
    step[st]=0;
    memset(vis,0,sizeof(vis));
    queue<int> que;
    if(!que.empty()) que.pop();
    que.push(st);
    vis[st]=true;
    while(!que.empty())
    {
        int cur=que.front();
        que.pop();
        for(int i=head[cur];~i;i=es[i].next)
        {
            int v=es[i].v;
            if(!vis[v])
            {
                que.push(v);
                step[v]=step[cur]+es[i].w;
                if(step[v]>maxn)
                {
                    maxn=step[v];
                    st=v;
                }
                vis[v]=true;
            }
        }
    }
    return maxn;
}
void ini()
{
    memset(head,-1,sizeof(head));
    sum=0;
}
int main()
{
    while(~scanf("%d%d",&n,&s))
    {
        ini();
        for(int i=1;i<n;i++)
        {
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            sum+=w;
            es[i].v=v,es[i].w=w,es[i].next=head[u];
            head[u]=i;
            es[i+n].v=u,es[i+n].w=w,es[i+n].next=head[v];
            head[v]=i+n;
        }
        bfs(s);
        printf("%d\n",2*sum-bfs(s));

    }
    return 0;
}



POJ 1849 Two(树的直径--树形DP)(好题)

原文:http://blog.csdn.net/kalilili/article/details/44275169

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!