题意
给你n个点的有向图,有m条边, q次查询,每次查询第k大的路径的长度
思路
对于每个点所出去的边先排个序,预处理一下,我没可以知道最开始最短的边肯定只有一条,所以我们把每个点出去的最短的边先放到优先队列里面, 然后最短的边肯定就是当前最短的路径,那要如何扩展路径了,我们每次求出当前最短的路径那么放到队列里的肯定是由这条路径扩展出来的,因为其他路径暂时不用扩,因为有更短的在队列里面,但我们放出(u,v)这条边e的时候, 扩展v最小的出边,和以u为始点的e的下一条边即可
AC_code:
/* Algorithm: Author: anthony1314 Creat Time: Time Complexity: */
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <string>
#include <vector>
#include <bitset>
#include <stack>
#include <cmath>
#include <deque>
#include <queue>
#include <list>
#include <set>
#include <map>
#define line printf("---------------------------\n")
#define mem(a, b) memset(a, b, sizeof(a))
#define pi acos(-1)
#define endl '\n'
using namespace std;
typedef long long ll;
typedef double db;
const int inf = 0x3f3f3f3f;
const int mod = 1e9+7;
const int maxn = 50000+10;
void add(int &x, int y) {
x = (x + y) % mod;
}
struct data {
ll w;
int u, v, p;
data() {}
data(ll _w, int _u, int _v, int _p) : w(_w), u(_u), v(_v), p(_p) {}
bool operator < (const data &b)const {
return w > b.w;
}
};
int n, m, q, u, v, k;
ll ans[maxn], w;
vector<pair<int, int> > g[maxn];
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int t;
cin>>t;
while(t--) {
cin>>n>>m>>q;
mem(ans, 0);
for(int i = 0; i <= n; i++) {
g[i].clear();
}
for(int i = 0; i < m; i++) {
cin>>u>>v>>w;
g[u].push_back(make_pair(w, v));
}
priority_queue<data> que;
for(int i = 1; i <= n; i++) {
sort(g[i].begin(), g[i].end());
}
for(int i = 1; i <= n; i++) {
if(!g[i].empty()) {
que.push(data(g[i][0].first, i, g[i][0].second, 0));
}
}
for(int j = 1; j <= 50000 && !que.empty(); j++){
data tmp = que.top();
que.pop();
ans[j] = tmp.w;
int tmpu = tmp.u, tmpv = tmp.v, tmpp = tmp.p;
if(g[tmpv].size()){
que.push(data(tmp.w + g[tmpv][0].first, tmpv, g[tmpv][0].second, 0));
}
if(tmpp != g[tmpu].size() - 1){
que.push(data(tmp.w + g[tmpu][tmpp+1].first - g[tmpu][tmpp].first, tmpu, g[tmpu][tmpp+1].second, tmpp+1));
}
}
while(q--){
cin>>k;
cout<<ans[k]<<endl;
}
}
return 0;
}