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 }
  • 相关阅读:
    poj 2411 Mondriaan's Dream 骨牌铺放 状压dp
    zoj 3471 Most Powerful (有向图)最大生成树 状压dp
    poj 2280 Islands and Bridges 哈密尔顿路 状压dp
    hdu 3001 Travelling 经过所有点(最多两次)的最短路径 三进制状压dp
    poj 3311 Hie with the Pie 经过所有点(可重)的最短路径 floyd + 状压dp
    poj 1185 炮兵阵地 状压dp
    poj 3254 Corn Fields 状压dp入门
    loj 6278 6279 数列分块入门 2 3
    VIM记事——大小写转换
    DKIM支持样本上传做检测的网站
  • 原文地址:https://www.cnblogs.com/0211ji/p/13442513.html
Copyright © 2011-2022 走看看