zoukankan      html  css  js  c++  java
  • The Longest Path 两种解法

    View Code
    /* 
    【题目来源】
    http://soj.me/show_problem.php?pid=1003&cid=567
    【题目分析】
    给定一些边确定一个图,即给定一些点之间的连通情况,保证给定的图没有回路,要求输出该图存在的最长路径。  
    【思路分析】
    . 根据给定信息构造图,用邻接表表示。(邻接矩阵明显很麻烦且效率不高) 
    . 将每一个顶点看成是树根,求出树的高度。
    . 得到一系列树的高度,最大的那个就是图中存在的最长路径。嗯对的。  
    【陷阱分析】
    .不应该被数据蒙骗,比如只给两条边但顶点不一定是1,2,3而有可能是1,99,100之类,所以数组开最大(题目范围1-100,所以开个105绝对够了) 
    【小小感受】
    用vector构造邻接表确实比较方便~ 学习了 
    */
    #include <iostream>
    #include <queue>
    #include <vector>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    #define Max 105
    int main()
    {
        int m;
        
        cin >> m;
        
        while (m--)
        {
            int n;
            
            cin >> n;
            
            vector<int> v[Max];//用vector构造邻接表 
            
            bool visit[Max];//记录该点是否已经被访问过 
            
            //构造邻接表 
            int temp1, temp2;
            for (int i = 0; i < n; ++i)
            {
                cin >> temp1 >> temp2;
                
                v[temp1].push_back(temp2);//无向图 temp1通temp2 
                
                v[temp2].push_back(temp1);//无向图 temp2通temp1
            }
            int ans = 0;
            
            //广搜咯~~~~ 求树的高度 
            for (int i = 1, j = 1; j < 3; j++)
            {
                int height[Max] = {0};
                
                memset(visit, 0, sizeof(visit));
                
                queue<int> q;
                
                q.push(i);
                
                visit[i] = 1;
                
                while (!q.empty())
                {   
                    int current = q.front();
                    
                    q.pop();
                    
                    for (int j = 0; j < v[current].size(); ++j)
                        if (!visit[v[current][j]])
                        {
                            q.push(v[current][j]);
                            
                            height[v[current][j]] = height[current]+1;//current所连接的节点的高度要比current多1 (其实这里理解成深度会更好) 
                            
                            visit[v[current][j]] = 1;
                        }
                    i = current;
                }
                int max = *max_element(height, height+Max);//该点作为树根时树的高度 
                
                if (ans < max) ans = max;//更新最大值 
            }
            
            cout << ans << endl;
        }
    }                                 
    View Code
    /*
    受乔帮主提点,这道题果然有更简单的做法 
    【思路分析】
    通俗来讲,把给定的图看成是一串珠子,随便拿起其中一颗,吊起来,那么再拿起此时这串珠子最下面的那颗,再吊起来
    ok,那么这时这串珠子的高度就是这一整个图存在的最长路径。
    好神奇。
    我自己粗略的证明 :
    随便拿起的这颗记为A,最底下那颗记为B。
    拿起A:
    此时B一定是最长路径里面的一点。 
    注意,此时A到B之间必定至少有2点是属于最长路径的,即除了B外还至少有一点C,并且这一点C在 A 到 A和B的中间。(若有多点,则C取最高的那一点) 
    (为什么C不能在B 到 A和B的中间呢,反证一下即可)
    离C最远的点现在必定是B 
    拿起B:
    现在离C最远的必定是最低的那点D,所以综合C在最长路径上,C离B最远,可得出BD为最长路径。  
    【小小疑问】 
    既然开始时是随机选一点,我还是不知道为什么选1就对,选temp2就不对。 
    */
    #include <iostream>
    #include <queue>
    #include <vector>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    #define Max 105
    int main()
    {
        int m;
        
        cin >> m;
        
        while (m--)
        {
            int n;
            
            cin >> n;
            
            vector<int> v[Max];//用vector构造邻接表 
            
            bool visit[Max];//记录该点是否已经被访问过 
            
            //构造邻接表 
            int temp1, temp2;
            for (int i = 0; i < n; ++i)
            {
                cin >> temp1 >> temp2;
                
                v[temp1].push_back(temp2);//无向图 temp1通temp2 
                
                v[temp2].push_back(temp1);//无向图 temp2通temp1
            }
            int ans = 0;
            
            //循环2次就行啦~~~ 
            for (int i = 1, j = 1; j < 3; j++)
            {
                int height[Max] = {0};
                
                memset(visit, 0, sizeof(visit));
                
                queue<int> q;
                
                q.push(i);
                
                visit[i] = 1;
                
                while (!q.empty())
                {   
                    int current = q.front();
                    
                    q.pop();
                    
                    for (int j = 0; j < v[current].size(); ++j)
                        if (!visit[v[current][j]])
                        {
                            q.push(v[current][j]);
                            
                            height[v[current][j]] = height[current]+1;//current所连接的节点的高度要比current多1 (其实这里理解成深度会更好) 
                            
                            visit[v[current][j]] = 1;
                        }
                    i = current;
                }
                int max = *max_element(height, height+Max);//该点作为树根时树的高度 
                
                if (ans < max) ans = max;//更新最大值 
            }
            
            cout << ans << endl;
        }
    }
  • 相关阅读:
    【设计模式】—— 观察者模式Observer
    【设计模式】—— 备忘录模式Memento
    【设计模式】—— 中介者模式Mediator
    【领域驱动】—— 领域驱动导读
    【设计模式】—— 迭代模式Iterator
    【设计模式】—— 解释器模式Interpret
    【设计模式】—— 命令模式Commond
    【设计模式】—— 职责链模式ChainOfResponsibility
    【设计模式】—— 代理模式Proxy
    系统设置参数说明11
  • 原文地址:https://www.cnblogs.com/chenyg32/p/2819400.html
Copyright © 2011-2022 走看看