uva10308 - Roads in the North 树形DP

Problem I

Roads in the North

Input: standardinput

Output: standardoutput

Time Limit: 2seconds

Memory Limit: 32MB

 

Building and maintaining roadsamong communities in the far North is an expensive business. With this in mind,the roads are built in such a way that there is only one route from a villageto a village that does not pass through some other village twice.

Given is an area in the far North comprising anumber of villages and roads among them such that any village can be reached byroad from any other village. Your job is to find the road distance between thetwo most remote villages in the area.

The area has up to 10,000 villages connected by road segments. The villages arenumbered from1.

Input

The input contains several sets of input. Eachset of input is a sequence of lines, each containing three positive integers:the number of a village, the number of a different village, and the length ofthe road segment connecting the villages in kilometers. All road segments aretwo-way. Two consecutive sets are separated by a blank line.

Output

For each set of input, you are to output a singleline containing a single integer: the road distance between the two most remotevillages in the area.

Sample Input

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

Sample Output

22

  第一次做树形DP,感觉就是在树上做一般的DP,在树上找关系。

  这道题是没有环的,也就是一个地方到另一个地方只有一种走法。要在图上找两个点,使他们之间的距离最长。

  那么两个点一定都是叶子节点(如果不是叶子节点,那么一定还可以延伸),这两个点连接的路径中经过的点都是他们的父节点,包括他们自己。

  只要遍历每个点,把这个点当做父节点,找到他子树中最长的一条路径和次长的一条路径加起来就是以这个点为父节点的最长路径。

  随时更新最大值就行了。

 DP 既然在树上,那就需要节点和节点之间的连接关系,所以应该都会用到vector,如果有多个参数,可以写个结构体,vector<结构体名>a[N],两个参数可以用pair,vector容器的push_back(t)是在容器的最后添加一个值为t的数据,还有push_front()是在前面加。一开始要先clear(),另外还有empty()之类的很多。。到时用到再看吧=。=

  当然也可以不用vector,自己写个连接表也行。

  代码:

  用vector的

#include<cstring>
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
#define INF 0x3f3f3f3f
using namespace std;
typedef pair<int,int> pii;
vector<pii> a[10010];
char str[100];
int ans,dp[10010][2],vis[10010];

void add(int u,int v,int w){
    pii t;
    t.first=v;
    t.second=w;
    a[u].push_back(t);
    t.first=u;
    a[v].push_back(t);
}
void DFS(int r){
    vis[r]=1;
    int i,v,w;
    pii t;
    dp[r][0]=dp[r][1]=0;
    for(i=0;i<a[r].size();i++){
        t=a[r][i];
        v=t.first;
        w=t.second;
        if(!vis[v]){
            DFS(v);
            if(dp[v][0]+w>dp[r][0]){
                dp[r][1]=dp[r][0];
                dp[r][0]=dp[v][0]+w;
            }
            else if(dp[v][0]+w>dp[r][1]) dp[r][1]=dp[v][0]+w;
        }
    }
    if(dp[r][0]+dp[r][1]>ans) ans=dp[r][0]+dp[r][1];
}
int main(){
    freopen("in.txt","r",stdin);
    while(gets(str)){
        int u,v,w,i;
        for(i=0;i<10010;i++) a[i].clear();
        while(str[0]){
            sscanf(str,"%d%d%d",&u,&v,&w);
            add(u,v,w);
            if(!gets(str)) break;
        }
        ans=0;
        memset(vis,0,sizeof(vis));
        DFS(1);
        printf("%d\n",ans);
    }
    return 0;
}

 连接表的

 

#include<cstring>
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
#define INF 0x3f3f3f3f
using namespace std;
char str[100];
int ans,e,dp[10010][2],vis[10010],edge[1000000][2],head[10010],next[10010];
void add(int u,int v,int w){
    edge[++e][0]=v;
    edge[e][1]=w;
    next[e]=head[u];
    head[u]=e;
    edge[++e][0]=u;
    edge[e][1]=w;
    next[e]=head[v];
    head[v]=e;
}

void DFS(int r){
    vis[r]=1;
    int i,v,w;
    dp[r][0]=dp[r][1]=0;
    for(i=head[r];i;i=next[i]){
        v=edge[i][0];
        w=edge[i][1];
        if(!vis[v]){
            DFS(v);
            if(dp[v][0]+w>dp[r][0]){
                dp[r][1]=dp[r][0];
                dp[r][0]=dp[v][0]+w;
            }
            else if(dp[v][0]+w>dp[r][1]) dp[r][1]=dp[v][0]+w;
        }
    }
    if(dp[r][0]+dp[r][1]>ans) ans=dp[r][0]+dp[r][1];
}
int main(){
    freopen("in.txt","r",stdin);
    while(gets(str)){
        int u,v,w,i;
        e=0;
        memset(head,0,sizeof(head));
        memset(next,0,sizeof(next));
        while(str[0]){
            sscanf(str,"%d%d%d",&u,&v,&w);
            add(u,v,w);
            if(!gets(str)) break;
        }
        ans=0;
        memset(vis,0,sizeof(vis));
        DFS(1);
        printf("%d\n",ans);
    }
    return 0;
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值