zoukankan      html  css  js  c++  java
  • 树的直径,树形DP,DFS——POJ1958

    题目链接

    题目含义

    就是建一个树,让你求最大直径

    下面用分别用DP和DFS的方法

    题目代码

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    using namespace std;
    const int maxn=5e4+7;
    int n,m,tot,a,b,c,ans;
    char cc;
    int head[maxn],d[maxn];
    struct node{
        int to,w,next;
    }edge[maxn*2];
    void add(int u,int v,int w){
        edge[tot].to=v;
        edge[tot].w=w;
        edge[tot].next=head[u];
        head[u]=tot++;
    }
    void dfs(int u,int fa){
        for(int i=head[u];i!=-1;i=edge[i].next){
            int v=edge[i].to;
            if(v==fa)continue;
            dfs(v,u);
            ans=max(ans,d[u]+d[v]+edge[i].w);
            d[u]=max(d[u],d[v]+edge[i].w);
        }
    }
    int main(){
        scanf("%d%d",&n,&m);
        tot=0;
        memset(d,0,sizeof(d));
        memset(head,-1,sizeof(head));
        for(int i=1;i<=m;i++){
            scanf("%d%d%d %c",&a,&b,&c,&cc);
            add(a,b,c);add(b,a,c);
        }
        ans=0;
        dfs(1,0);
        printf("%d
    ",ans);
        return 0;
    }
    树形DP

    树形DP的思想是用任意一个节点作为根

    然后找出这个根的深度最大的两个子树

    这两个子树的深度之和就是最大直径

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    using namespace std;
    const int maxn=5e4+7;
    int n,m,tot,a,b,c,ans;
    char cc;
    int head[maxn],dis[maxn];
    struct node{
        int to,w,next;
    }edge[maxn*2];
    void add(int u,int v,int w){
        edge[tot].to=v;
        edge[tot].w=w;
        edge[tot].next=head[u];
        head[u]=tot++;
    }
    void dfs(int u,int fa){
        for(int i=head[u];i!=-1;i=edge[i].next){
            int v=edge[i].to;
            if(v==fa)continue;
            dis[v]=dis[u]+edge[i].w;
            dfs(v,u);
        }
    }
    int main(){
        scanf("%d%d",&n,&m);
        tot=0;
        memset(head,-1,sizeof(head));
        for(int i=1;i<=m;i++){
            scanf("%d%d%d %c",&a,&b,&c,&cc);
            add(a,b,c);add(b,a,c);
        }
        int ans_max=0,ans_index=0;
        memset(dis,0,sizeof(dis));
        dfs(1,0);
        for(int i=1;i<=n;i++){
            if(dis[i]>ans_max){
                ans_max=dis[i];
                ans_index=i;
            }
        }
        memset(dis,0,sizeof(dis));
        dfs(ans_index,0);
        for(int i=1;i<=n;i++)
            if(dis[i]>ans_max)
                ans_max=dis[i];
        printf("%d
    ",ans_max);
        return 0;
    }
    两次DFS

    两次DFS的思想是先用任意一个节点作为根

    找到离他最远的节点的深度ANS_MAX和这个节点的位置ANS_INDEX

    然后再以找到的这个节点作为根

    找出离他最远的节点的深度,与ANS_MAX做比较,就能找出最大直径

  • 相关阅读:
    VueCLI3如何更改安装时的包管理器
    查天气43课-46课
    【Python第31课到42课】
    【Python第16课到30课 】
    Python笔记
    【AC】九度OJ题目1153:括号匹配问题
    【AC】九度OJ题目1436:Repair the Wall
    【WA】九度OJ题目1435:迷瘴
    Matlab图片改颜色通道不改名存储
    [Linux 操作] awk操作の 打印图片路径
  • 原文地址:https://www.cnblogs.com/helman/p/11271948.html
Copyright © 2011-2022 走看看