K-th Path(CF-1196F)

Problem Description

You are given a connected undirected weighted graph consisting of nn vertices and mm 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 dd is the matrix of shortest paths, where di,jdi,j is the length of the shortest path between vertices i and j (1≤i<j≤n), then you need to print the kk-th element in the sorted array consisting of all di,jdi,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)n), 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 kk, correspondingly.

Then mm 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 ii to jj and from jj to ii are counted as one).

Examples

Input

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

Output

3

Input

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

Output

9

题意:给出一 n 个点 m 条边的无向带权图,定义路径为任意两点的距离,输出图中第 k 条小的路径

思路:

由于路径定义为任意两点的距离,要在图中找第 k 小的路径,那么第 k 小的路径一定是在前 k 条边所连接的点中的路径中,因此可以对 m 条边进行排序,选前 k 条边,将每条边连接的点记录下来跑 Floyd,然后找第 k 大的边即可

此外,选出来点后,点的编号可能很大,无法建立邻接矩阵,因此需要对点进行离散化再跑 Floyd

Source Program

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<bitset>
#define EPS 1e-9
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
#define LL long long
const int MOD = 1E9+7;
const int N = 5000+5;
const int dx[] = {-1,1,0,0,-1,-1,1,1};
const int dy[] = {0,0,-1,1,-1,1,-1,1};
using namespace std;
struct Edge {
    LL x,y;
    LL w;
    Edge() {}
    Edge(LL x,LL y,LL w):x(x),y(y),w(w) {}
    bool operator <(const Edge &rhs)const {
        return w<rhs.w;
    }
};
vector<Edge> edge;
vector<LL> node;
LL dis[N][N];
int main() {
    LL n,m,k;
    scanf("%lld%lld%lld",&n,&m,&k);
    for(int i=1;i<=m;i++){
        LL x,y,w;
        scanf("%lld%lld%lld",&x,&y,&w);
        edge.push_back(Edge(x,y,w));
    }
    sort(edge.begin(),edge.end());//将边按权值大小排序

    LL edgeNum=min(m,k);
    for(int i=0;i<edgeNum;i++){//选取前k大的边并记录每条边的邻接点
        LL x=edge[i].x;
        LL y=edge[i].y;
        node.push_back(x);
        node.push_back(y);
    }

    sort(node.begin(),node.end());//将点排序后去重
    node.erase(unique(node.begin(),node.end()),node.end());

    memset(dis,INF,sizeof(dis));
    LL nodeNum=node.size();
    for(int i=0;i<nodeNum;i++)
        dis[i][i]=0;

    for(int i=0;i<edgeNum;i++){//离散化后存点
        LL x=lower_bound(node.begin(),node.end(),edge[i].x)-node.begin();
        LL y=lower_bound(node.begin(),node.end(),edge[i].y)-node.begin();
        dis[x][y]=min(dis[x][y],edge[i].w);
        dis[y][x]=min(dis[x][y],edge[i].w);
    }

    for(int k=0;k<nodeNum;k++)//Floyd求全源最短路
        for(int i=0;i<nodeNum;i++)
            for(int j=0;j<nodeNum;j++)
                dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);

    vector<LL> res;
    for (int i=0; i<nodeNum;i++)
        for (int j=0;j<i;j++)
            res.push_back(dis[i][j]);

    sort(res.begin(),res.end());

    printf("%lld\n",res[k-1]);//第k小的路径
    return 0;
}

 

posted @   老程序员111  阅读(7)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示