题意:
给一张n个点m条边的无向图,求所有点对的最短路径第k 小,且u到v最短路径与v到u路径只算一次,
(n,m<=2e5,k<=400)
分析:
把所有边按边权从小到大排序,然后取前k条跑floyd,将floyd跑出的所有边排序
答案就是求出得第k条边的长度
题目说k最大400,所以点最多800,完全吃得消
只取前k条是因为第k条之后的路径不可能是是所有最短路径的第k小,所以直接不管了
由于点的编号可能过大,所以要将点编号离散化(否则二维数组放不下)
code:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#define int long long
using namespace std;
const int N=800+5;
const int M=2e5+5;
struct Node{
int a,b,c;
bool operator<(Node a){
return c<a.c;
}
}e[M];
int xx[N],num;
int g[N][N];
int n,m,k;
void init(){
cin>>n>>m>>k;
for(int i=0;i<m;i++){
cin>>e[i].a>>e[i].b>>e[i].c;
}
sort(e,e+m);
for(int i=0;i<k;i++){//把点离散化,否则下标太大了
xx[++num]=e[i].a;
xx[++num]=e[i].b;
}
sort(xx+1,xx+1+num);
num=unique(xx+1,xx+1+num)-xx-1;
}
void floyd(){
for(int i=1;i<=num;i++){
for(int j=1;j<=num;j++){
g[i][j]=1e18;
}
}
for(int i=0;i<k;i++){
int a=lower_bound(xx+1,xx+1+num,e[i].a)-xx;
int b=lower_bound(xx+1,xx+1+num,e[i].b)-xx;
g[a][b]=g[b][a]=e[i].c;
}
for(int k=1;k<=num;k++){
for(int i=1;i<=num;i++){
for(int j=i+1;j<=num;j++){
g[i][j]=g[j][i]=min(g[i][j],g[i][k]+g[k][j]);
}
}
}
}
void solve(){
vector<int>ans;
for(int i=1;i<=num;i++){
for(int j=i+1;j<=num;j++){
if(g[i][j]!=1e18){
ans.push_back(g[i][j]);
}
}
}
sort(ans.begin(),ans.end());
cout<<ans[k-1]<<endl;
}
signed main(){
ios::sync_with_stdio(0);
init();
floyd();
solve();
return 0;
}