F. K-th Path
time limit per test2.5 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
You are given a connected undirected weighted graph consisting of n vertices and m edges.
You need to print the k-th smallest shortest path in this graph (paths from the vertex to itself are not counted, paths from i to j and from j to i are counted as one).
More formally, if d is the matrix of shortest paths, where di,j is the length of the shortest path between vertices i and j (1≤i<j≤n), then you need to print the k-th element in the sorted array consisting of all di,j, where 1≤i<j≤n.
Input
The first line of the input contains three integers n,m and k (2≤n≤2⋅105, n−1≤m≤min(n(n−1)2,2⋅105), 1≤k≤min(n(n−1)2,400) — the number of vertices in the graph, the number of edges in the graph and the value of k, correspondingly.
Then m lines follow, each containing three integers x, y and w (1≤x,y≤n, 1≤w≤109, x≠y) denoting an edge between vertices x and y of weight w.
It is guaranteed that the given graph is connected (there is a path between any pair of vertices), there are no self-loops (edges connecting the vertex with itself) and multiple edges (for each pair of vertices x and y, there is at most one edge between this pair of vertices in the graph).
Output
Print one integer — the length of the k-th smallest shortest path in the given graph (paths from the vertex to itself are not counted, paths from i to j and from j to i are counted as one).
Examples
inputCopy
6 10 5
2 5 1
5 3 9
6 2 2
1 3 1
5 1 8
6 5 10
1 6 5
6 4 6
3 6 2
3 4 5
outputCopy
3
inputCopy
7 15 18
2 6 3
5 7 4
6 5 4
3 6 9
6 7 7
1 6 4
7 1 6
7 2 1
4 3 2
3 2 8
5 3 6
2 5 5
3 7 9
4 1 8
2 1 1
outputCopy
9
题目大意:求所有两点间的第K大路径。
直接暴力必然会TLE,但是由于K比较小,所以我们必然只需要把前K大的边存下来跑最短路,然后就AC了。
对于每个点跑最短路。
因为边很少,每次更新的点也少,所以我们需要把这些点记录一下,来清空,不能每次O(n)去清空,很显然(但是我sb了,直接TLE)。
AC代码:
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+10;
int n,m,k,d[N],flag,vis[N],st[N];
int head[N],nex[N<<1],to[N<<1],w[N<<1],tot;
vector<int> res;
struct node{
int u,v,w;
}t[N];
inline bool cmp(node a,node b){return a.w<b.w;}
inline void add(int a,int b,int c){
to[++tot]=b; nex[tot]=head[a]; w[tot]=c; head[a]=tot;
}
void dijkstra(int x){
priority_queue<pair<int,int> > q;
d[x]=0; q.push({0,x}); vector<int> tem;
while(q.size()){
int u=q.top().second; q.pop();
if(vis[u]) continue; vis[u]=1;
for(int i=head[u];i;i=nex[i]){
if(d[to[i]]>d[u]+w[i]){
d[to[i]]=d[u]+w[i]; st[to[i]]++;
if(st[to[i]]==1) tem.push_back(to[i]);
if(!vis[to[i]]) q.push({-d[to[i]],to[i]});
}
}
}
for(int i=0;i<tem.size();i++) res.push_back(d[tem[i]]);
d[x]=0x3f3f3f3f3f3f3f3f; vis[x]=0; st[x]=0;
for(int i=0;i<tem.size();i++)
d[tem[i]]=0x3f3f3f3f3f3f3f3f,vis[tem[i]]=0,st[tem[i]]=0;
}
signed main(){
cin>>n>>m>>k; memset(d,0x3f,sizeof d);
for(int i=1;i<=m;i++) scanf("%lld %lld %lld",&t[i].u,&t[i].v,&t[i].w);
sort(t+1,t+1+m,cmp);
for(int i=1;i<=k&&i<=m;i++) add(t[i].u,t[i].v,t[i].w),add(t[i].v,t[i].u,t[i].w);
for(int i=1;i<=n;i++) dijkstra(i);
sort(res.begin(),res.end());
cout<<res[k*2-1]<<endl;
return 0;
}