zoukankan      html  css  js  c++  java
  • 5.14每日一题题解

    紧急救援

    涉及知识点:

    • Dijkstra/DFS

    solution:

    • (这个题有两种做法第一种是Dijkstra + DFS)
    • (这个做法呢,这个解法是:我们把所有的最短路求出来,然后再根据救援人数最多进行深搜,回溯)
    • (另一个是 Dijkstra + 记录)
    • (代码我已经把重要的难以理解的地方加上了注释)
    • (由于N的范围是500,那么我们可以判定这个图为稠密图,需要用邻接矩阵来存,当然如果用邻接表来存的话,那就需要用对优化的Dijkstra)
    • (最好是用邻接表来存)
    • (如果t这个点可以更新v这个点,那么到达v的路径,就应该和到达t的路径一样,人数就应该是到达t的总人数加上在v的总人数)
    • (并且v的前驱就是t,pre[v] = t)
    • (如果此时t到v的距离和原点到达v的距离相等,那么在v的路径总数应该是nums[v]+=nums[t])
    • (如果人数可以更新的话,那么我们就更新一下总人数,pre[v] = t,w[v] = w[t] + weights[v])

    std:

    
    #include <iostream>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    
    using namespace std;
    
    const int N = 510;
    int n,m;
    int dist[N];
    bool st[N];
    int weights[N];
    int g[N][N];
    int w[N];
    int start,en;
    
    vector<int>pre[N];// 记录所有的最短路径是怎么走的
    
    void Dijkstra()
    {
        memset(dist,0x3f,sizeof dist);
    
        dist[start] = 0;
    
        for(int i = 0;i < n;i++)
        {
            int t = -1;
    
            for(int j = 0;j < n;j++)
            {
                if(!st[j]&&(t==-1||dist[t]>dist[j]))t = j;
            }
            if(t==-1)return;
            st[t] = true;
            for(int v = 0;v < n;v++)
            {
                // 如果当前这个点t可以更新v这个点,那么,v的前驱就是t,由于v之前可能有别的前驱,所以我们需要把pre[v],清空
                if(dist[v] > dist[t] + g[t][v])
                {
                    dist[v] = dist[t] + g[t][v];
                    pre[v].clear();
                    pre[v].push_back(t);
    
                } // t为v的前驱之一
                else if(dist[v] == dist[t] + g[t][v])
                {
                    pre[v].push_back(t);
                }
            }
        }
    }
    vector<int>path;//记录答案
    vector<int>tempPath;// 记录临时答案
    int val = 0;// 记录最大人数
    int cnt = 0;// 记录最短路的条数
    
    void dfs(int v)
    {
        tempPath.push_back(v);// 把当前点放到vector里面
        if(v == start)
        {
            cnt++;
            int value = 0;
            for(auto &x : tempPath)
            {
                value += weights[x];
            }
    
            if(value > val)
            {
                val = value;
                path = tempPath;
            }
            tempPath.pop_back();
            return;
        }
        
        for(auto &x : pre[v])
        {
            dfs(x);
        }
        
        tempPath.pop_back();//回溯
    }
    int main()
    {
        ios::sync_with_stdio(false);
        cin >> n >> m >> start >> en;
        memset(g,0x3f,sizeof g);
        for(int i = 0;i < n;i++)
        {
            cin >> weights[i];
        }
        for(int i = 0;i < m;i++)
        {
            int a,b,c;
            cin >> a >> b >> c;
            g[a][b] = g[b][a] = min(g[a][b],c);
        }
        Dijkstra();
        for(auto &x : pre[en])
        {
            dfs(x);
        }
        cout << cnt <<" " << val + weights[en] << endl;
        int size = path.size();
        for(int i = size - 1;~i;i--)
        {
            cout << path[i] << " ";
        }
        cout << en;
        return 0;
    }
    
    // 第二种做法
    #include <iostream>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    
    using namespace std;
    
    const int N = 510;
    int n,m;
    int dist[N];
    int pre[N];
    bool st[N];
    int nums[N];
    int weights[N];
    int g[N][N];
    int w[N];
    int start,en;
    
    void Dijkstra()
    {
        memset(dist,0x3f,sizeof dist);
    
        dist[start] = 0;
    
        w[start] = weights[start];
    
        for(int i = 0;i <= n;i++)
        {
            pre[i] = i;
        }
    
        nums[start] = 1;
    
        for(int i = 0;i < n;i++)
        {
            int t = -1;
    
            for(int j = 0;j < n;j++)
            {
                if(!st[j]&&(t==-1||dist[t]>dist[j]))t = j;
            }
            
            
            if(t==-1)return;
    
            st[t] = true;
    
            for(int v = 0;v < n;v++)
            {
                if(dist[v] > dist[t] + g[t][v])
                {
                    dist[v] = dist[t] + g[t][v];
    
                    nums[v] = nums[t];
    
                    w[v] = w[t] + weights[v];
    
                    pre[v] = t;
                }
                else if(dist[v] == dist[t] + g[t][v])
                {
                    nums[v] = nums[t] + nums[v];
    
                    if(w[t] + weights[v] > w[v])
                    {
                        pre[v] = t;
                        w[v] = w[t] + weights[v];
                    }
                }
            }
        }
    
    }
    
    vector<int>road;
    
    void dfs(int e)
    {
        if(e==start){
            road.push_back(e);return ;
        }
        dfs(pre[e]);
        road.push_back(e);
    }
    
    int main()
    {
        
        ios::sync_with_stdio(false);
        
        cin >> n >> m >> start >> en;
    
        memset(g,0x3f,sizeof g);
    
        for(int i = 0;i < n;i++)
        {
            cin >> weights[i];
        }
    
        for(int i = 0;i < m;i++)
        {
            int a,b,c;
            cin >> a >> b >> c;
            g[a][b] = g[b][a] = min(g[a][b],c);
        }
    
        Dijkstra();
    
        cout << nums[en] << " " << w[en] << endl;
    
        bool tf = false;
    
        dfs(en);
    
        for(auto &x : road)
        {
            if(tf)cout << " ";
            cout << x;
            tf = true;
        }
    
        return 0;
    }
    
  • 相关阅读:
    ASP.NET程序中常用的三十三种代码【转】
    BTree,BTree,B+Tree,B*Tree都是什么
    调用Google地图
    JS特效总结
    2005 加入博客园
    .net Windows服务程序安装与安装程序的制作
    七夕,爱似流年
    JS+CSS仿魔兽游戏进入进度条特效
    常用正则表达式
    Google翻译网站添加Google翻译,让老外也看的懂你的网站
  • 原文地址:https://www.cnblogs.com/QFNU-ACM/p/12887276.html
Copyright © 2011-2022 走看看