• 「日常训练」湫湫系列故事——设计风景线(HDU-4514)


    题意与分析

    中文题目,木得题意的讲解谢谢。
    然后还是分解成两个任务:a)判环,b)找最长边。
    对于这样一个无向图,强行转换成负权然后bellman-ford算法求最短是难以实现的,所以感谢没有环——我们可以当作一棵树来做,然后就直接是树的直径的做法了。
    这里同之前的题解的思路不一样的是,采用了动态规划的思路来做树的直径。
    (dp[now][0])为从now出发的最长路径,而(dp[now][1])是从now出发的次长路径。
    对从now走出来的每条路径都有做一次判断,首先判断它是否比当前最长的路径的长,如果是,那么它变最长当前最长变次长;如果它比最长短(这个很重要,否则会出现最长与次长的节点相重复),那么判断它是否比次长的长,如果是,更新之。
    这样,每个过now的最长边就是(dp[now][0]+dp[now][1]),遍历一遍更新之。
    值得注意的是,这题没有硬点只有一个连通分量。不要在这边翻车了。

    代码

    /* 
     * Filename: hdu4514.cpp
     * Date: 2018-11-05
     */
    
    #include <bits/stdc++.h>
    
    #define INF 0x3f3f3f3f
    #define PB emplace_back
    #define MP make_pair
    #define fi first
    #define se second
    #define rep(i,a,b) for(repType i=(a); i<=(b); ++i)
    #define per(i,a,b) for(repType i=(a); i>=(b); --i)
    #define ZERO(x) memset(x, 0, sizeof(x))
    #define MS(x,y) memset(x, y, sizeof(x))
    #define ALL(x) (x).begin(), (x).end()
    
    #define QUICKIO                  
        ios::sync_with_stdio(false); 
        cin.tie(0);                  
        cout.tie(0);
    #define DEBUG(...) fprintf(stderr, __VA_ARGS__), fflush(stderr)
    
    using namespace std;
    using pi=pair<int,int>;
    using repType=int;
    using ll=long long;
    using ld=long double;
    using ull=unsigned long long;
    
    int n,m;
    const int MAXN=100005;
    struct Edge
    {
        int u,v,w;
        Edge() {}
        Edge(int _u, int _v, int _w):
            u(_u), v(_v), w(_w) {}
    };
    vector<Edge> edges;
    
    vector<int> G[MAXN];
    void add_edge(int u,int v,int w)
    {
        edges.PB(u,v,w);
        G[u].PB(edges.size()-1);
    }
    
    int pa[MAXN];
    int find_pa(int x)
    {
        return pa[x]==x?x:pa[x]=find_pa(pa[x]);
    }
    bool union_pa(int x,int y)
    {
        int fx=find_pa(x),
            fy=find_pa(y);
        if(fx!=fy) pa[fx]=fy;
        else return false;
        return true;
    }
    
    bool vis[MAXN];
    int diameter, dp[MAXN][5];
    void dfs(int now, int par)
    {
        vis[now]=true;
        rep(i,0,int(G[now].size())-1)
        {
            Edge& e=edges[G[now][i]];
            int nxt=e.v;
            if(vis[nxt]) continue;
            dfs(nxt,now);
            if(dp[now][0]<dp[nxt][0]+e.w)
            {
                dp[now][1]=dp[now][0];
                dp[now][0]=dp[nxt][0]+e.w;
            }
            else if(dp[now][1]<dp[nxt][0]+e.w)
                dp[now][1]=dp[nxt][0]+e.w;
        }
        if(diameter<dp[now][0]+dp[now][1]) diameter=dp[now][0]+dp[now][1];
    }
    
    int
    main()
    {
        while(scanf("%d%d", &n, &m)==2)
        {
            edges.clear(); rep(i,1,n) G[i].clear();
            iota(pa+1,pa+n+1,1);
            bool has_loop=false;
            rep(i,1,m)
            {
                int u,v,w;
                scanf("%d%d%d", &u, &v, &w);
                if(has_loop) continue;
                add_edge(u,v,w);
                add_edge(v,u,w);
                if(find_pa(u)!=find_pa(v))
                {
                    union_pa(u,v);
                }
                else has_loop=true;
            }
            if(has_loop) printf("YES
    ");
            else
            {
                ZERO(vis);
                ZERO(dp);
                int ans=0;
                rep(i,1,n) if(!vis[i])
                {
                    diameter=0;
                    dfs(i,0);
                    ans=max(diameter,ans);
                }
                printf("%d
    ", ans);
            }
        }
        return 0;
    }
    
    如非注明,原创内容遵循GFDLv1.3发布;其中的代码遵循GPLv3发布。
  • 相关阅读:
    gbk与utf-8转换
    gdb注意事项
    Ubuntu导入证书
    Ubuntu 修改hosts
    GDB配置与.gdbinit的编写
    linux中用户的主目录~
    关于C++构造函数初始化顺序
    C++中的static关键字的总结
    Flutter移动电商实战 --(2)建立项目和编写入口文件
    Flutter移动电商实战 --(1)项目学习记录
  • 原文地址:https://www.cnblogs.com/samhx/p/HDU-4514.html
Copyright © 2020-2023  润新知