zoukankan      html  css  js  c++  java
  • path -第k短路

    题意:
    给你一个有向图,任意一个点和边都可以经过很多次,问你整个图中,任意起点终点的k短路的长度是多少?你需要回答q个询问,每个询问给一个k

    分析:
    没有起点和终点,那么我们就将所有的边放到优先级队列里面,建立一个最小堆,这样就可以从堆中取出最小边权的起点,然后去扩展这个起点的下一个边和下一个点的边,这样就可以找到前k条最小的边了

    链接:https://blog.csdn.net/c___c18/article/details/100085336

    链接里的代码可过,我照着链接代码写了一遍一直tl

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<queue>
     6 #include<stack>
     7 #include <bitset>
     8 #include<set>
     9 #include<map>
    10 #include<unordered_map>
    11 #include<vector>
    12 #include<cmath>
    13 typedef long long ll;
    14 using namespace std;
    15 typedef pair<ll, int> pa;
    16 const int N = 5e4 + 1000;
    17 vector<pa>ve[N];
    18 const int INF = 0x3f3f3f3f;
    19 int ans[N], maxk = 0, n, m, q, qq[N];
    20 struct node {
    21     int id, now, to;
    22     ll dis;
    23     //优先队列进队时,权重小的放前面
    24     bool operator <(const node& a)const {
    25         return dis > a.dis;
    26     }
    27 };
    28 priority_queue<node> pr;
    29 void dfs() {
    30     int cnt = 0;
    31     while (!pr.empty()) {
    32         //选择整张图的权重最小值
    33         node x = pr.top();
    34         pr.pop();
    35         node t;
    36         ans[++cnt] = x.dis;
    37         if (cnt >= maxk) {
    38             break;
    39         }
    40         //当x点还有临边时,将x的下一个最短权重边加入队列
    41         if (x.id + 1 < ve[x.now].size()) {
    42             t.dis = x.dis - ve[x.now][x.id].first + ve[x.now][x.id + 1].first;
    43             t.id = x.id + 1;
    44             t.to = ve[x.now][x.id + 1].second;
    45             t.now = x.now;
    46             pr.push(t);
    47         }
    48         //若当前最短边的汇点有指向别的点的边,则取汇点y到别的边z的最短长度边,x,z加入队列
    49         if (ve[x.to].size()) {
    50             t.dis = x.dis + ve[x.to][0].first;
    51             t.id = 0;
    52             t.now = x.to;
    53             t.to = ve[x.to][0].second;
    54             pr.push(t);
    55         }
    56     }
    57 }
    58 int main() {
    59     int T;
    60     cin >> T;
    61     while (T--) {
    62         //清空优先队列和容器
    63         while (!pr.empty()) {
    64             pr.pop();
    65         }
    66         cin >> n >> m >> q;
    67         for (int i = 1; i <= n; i++) {
    68             ve[i].clear();
    69         }
    70         //将w和v放入下标为u的容器内
    71         for (int i = 1; i <= m; i++) {
    72             int u, v, w;
    73             cin >> u >> v >> w;
    74             ve[u].push_back({ w,v });
    75         }
    76         //将顶点内的权重排序,把顶点到临边权重最小值放入优先队列
    77         for (int i = 1; i <= n; i++) {
    78             if (ve[i].size()) {
    79                 sort(ve[i].begin(), ve[i].end());
    80                 pr.push({ 0,i,ve[i][0].second,ve[i][0].first });
    81             }
    82         }
    83         //找出k的最大值
    84         for (int i = 1; i <= q; i++) {
    85             cin >> qq[i];
    86             maxk = max(maxk, qq[i]);
    87         }
    88         dfs();
    89         for (int i = 1; i <= q; i++) {
    90             cout << ans[qq[i]] << endl;
    91         }
    92     }
    93     return 0;
    94 }
  • 相关阅读:
    codevs1842 递归第一次
    codevs1501 二叉树最大宽度和高度
    (noi.openjudge.cn) 1.5编程基础之循环控制T36——T45
    (noi.openjudge.cn) 1.7编程基础之字符串T21——T30
    (noi.openjudge.cn) 1.9编程基础之顺序查找T06——T15
    (noi.openjudge.cn) 1.9编程基础之顺序查找T01——T05
    (noi.openjudge.cn) 1.7编程基础之字符串T31——T35
    (noi.openjudge.cn) 1.8编程基础之多维数组T21——T25
    Objective-C/C++混编编译器设置
    UITableView使用指南
  • 原文地址:https://www.cnblogs.com/0211ji/p/13442513.html
Copyright © 2011-2022 走看看