• POJ 1985 Cow Marathon && POJ 1849 Two(树的直径)


    树的直径:树上的最长简单路径。

    求解的方法是bfs或者dfs。先找任意一点,bfs或者dfs找出离他最远的那个点,那么这个点一定是该树直径的一个端点,记录下该端点,继续bfs或者dfs出来离他最远的一个点,那么这两个点就是他的直径的短点,距离就是路径长度。具体证明见http://www.cnblogs.com/wuyiqi/archive/2012/04/08/2437424.html 其实这个自己画画图也能理解。

    POJ 1985

    题意:直接让求最长路径。

    可以用dfs也可以用bfs

    bfs代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    using namespace std;
    typedef pair<int, int> pii;
    const int maxn = 200000;
    int tot, head[maxn];
    struct Edge {
        int to, next, w;
    }edge[maxn];
    bool vis[maxn];
    void init()
    {
        tot = 0;
        memset(head, -1, sizeof(head));
    }
    void addedge(int u, int v, int w)
    {
        edge[tot].to = v;
        edge[tot].w = w;
        edge[tot].next = head[u];
        head[u] = tot++;
    }
    int maxx, pos;
    void bfs(int p)//从p开始找到离他最远的那个点,距离保存在maxx当中 
    {
        maxx = -1;
        memset(vis, false, sizeof(vis));
        queue<pii> Q;
        vis[p] = true;
        pii cur, nex;
        cur.first = p; cur.second = 0;//pair的first表示节点编号,second表示权值 
        Q.push(cur);
        while (!Q.empty())
        {
            cur = Q.front();
            Q.pop();
            for (int i = head[cur.first]; i != -1; i = edge[i].next)
            {
                int v = edge[i].to;
                if (vis[v]) continue;
                vis[v] = true;
                nex.first = v; nex.second = cur.second + edge[i].w;
                if (maxx < nex.second)//如果找到最大的就替换 
                {
                    maxx = nex.second;
                    pos = v;
                }
                Q.push(nex);
            }
        }
    }
    int main()
    {
        int n, m;
        while (~scanf("%d %d", &n, &m))
        {
            init();
            int u, v, w;
            for (int i = 0; i < m; i++)
            {
                scanf("%d %d %d %*s", &u, &v, &w);
                addedge(u, v, w);
                addedge(v, u, w);
            }
            bfs(1);
            bfs(pos);
            printf("%d
    ", maxx);
        }    
        return 0;
    } 
    View Code

    dfs代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    using namespace std;
    typedef pair<int, int> pii;
    const int maxn = 200000;
    int tot, head[maxn];
    struct Edge {
        int to, next, w;
    }edge[maxn];
    bool vis[maxn];
    void init()
    {
        tot = 0;
        memset(head, -1, sizeof(head));
    }
    void addedge(int u, int v, int w)
    {
        edge[tot].to = v;
        edge[tot].w = w;
        edge[tot].next = head[u];
        head[u] = tot++;
    }
    int maxx, pos;
    void dfs(int p, int fa, int w)
    {
        for (int i = head[p]; i != -1; i = edge[i].next)
        {
            int v = edge[i].to;
            if (v == fa || vis[v]) continue;
            vis[v] = true;
            if (w + edge[i].w > maxx)
            {
                maxx = w + edge[i].w;
                pos = v;
            }
            dfs(v, p, w + edge[i].w);
            vis[v] = false;
        }
    } 
    void solve()
    {
        memset(vis, false, sizeof(vis));
        maxx = -1;
        dfs(1, 0, 0);
        maxx = -1;
        dfs(pos, 0, 0);
        printf("%d
    ", maxx);
    }
    int main()
    {
        int n, m;
        while (~scanf("%d %d", &n, &m))
        {
            init();
            int u, v, w;
            for (int i = 0; i < m; i++)
            {
                scanf("%d %d %d %*s", &u, &v, &w);
                addedge(u, v, w);
                addedge(v, u, w);
            }
            solve();
        }    
        return 0;
    } 
    View Code

    POJ 1849

    题意: 给出一棵树,两个人从给定的点s开始走,走完这棵树最少走的长度。

    思路:如果要回到当初的点,根据树的性质,那么一定是将这棵树走了两遍,但是题目要求可以停在任何位置,所以走不到两边,有些边走了一遍,求最小花费,那么一定是最长的那条路径走了一遍,其他都是两遍,这样才是最小花费。仔细想想其实从哪个点开始走并不影响最后的结果。因为不管哪个点肯定都要走完。要使两个人走的简单路径最长,那么这两个人走的路径就是树的最长路径了。所以答案就是:两倍的所有路径权值之和减去树的直径

    代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    using namespace std;
    typedef pair<int, int> pii;
    const int maxn = 220000;
    int tot, head[maxn];
    struct Edge {
        int to, next, w;
    }edge[maxn];
    bool vis[maxn];
    void init()
    {
        tot = 0;
        memset(head, -1, sizeof(head));
    }
    void addedge(int u, int v, int w)
    {
        edge[tot].to = v;
        edge[tot].w = w;
        edge[tot].next = head[u];
        head[u] = tot++;
    }
    int maxx, pos;
    void bfs(int p)
    {
        maxx = -1;
        memset(vis, false, sizeof(vis));
        queue<pii> Q;
        pii cur, nex;
        cur.first = p; cur.second = 0;
        vis[p] = true;
        Q.push(cur);
        while (!Q.empty())
        {
            cur = Q.front();
            Q.pop();
            for (int i = head[cur.first]; i != -1; i = edge[i].next)
            {
                int v = edge[i].to;
                if (vis[v]) continue;
                vis[v] = true;
                nex.first = v; nex.second = cur.second + edge[i].w;
                if (nex.second > maxx)
                {
                    maxx = nex.second;
                    pos = v;
                }
                Q.push(nex);
            }
        }
    }
    int main()
    {
        int n, s;
        while (~scanf("%d %d", &n, &s))
        {
            init();
            int u, v, w, ans = 0;
            for (int i = 1; i < n; i++)
            {
                scanf("%d %d %d", &u, &v, &w);
                addedge(u, v, w);
                addedge(v, u, w);
                ans += w * 2;
            }
            bfs(s);
            bfs(pos);
            printf("%d
    ", ans - maxx);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Cannot find module 'express'
    txt简单写入
    URLRewriter 伪静态配置Demo
    利用css的sticky特性实现固定首列其他列滚动
    金数据表单接口请求(php)
    Android应用app数据请求捕捉三步走
    go语言模块开发概念与cron定时事务模块的使用
    万维网的发明
    UEditor扩展又拍云图片存储功能实践
    Html5+移动端小应用分享(得见)
  • 原文地址:https://www.cnblogs.com/Howe-Young/p/4778851.html
Copyright © 2020-2023  润新知