在加权无向图上求出一条从1号结点到N号结点的路径,使路径上第K+1大的边权尽量小

二分+最短路算法

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#define maxn 100010
using namespace std;
const int INF = 0x3f3f3f3f;
struct Node {
	int p;
	int len;
	Node(int a, int b) :p(a), len(b) {}
};
vector<Node>G[maxn];
void insert(int be, int en, int len) {
	G[be].push_back(Node(en, len));
}
bool operator <(const Node a, const Node b) {
	return a.len > b.len;
}
int vis[maxn];
int dis[maxn];
int n, m, k;
int dijstra(int be, int range) {
	memset(vis, 0, sizeof(vis));
	memset(dis, INF, sizeof(dis));
	priority_queue<Node>que;
	que.push(Node(be, 0));
	dis[be] = 0;
	while (!que.empty()) {
		Node ans = que.top();
		que.pop();
		if (vis[ans.p]) continue;
		vis[ans.p] = 1;
		int x = ans.p;
		for (int i = 0; i < G[x].size(); i++) {
			int p = G[x][i].p;
			int len;
			if (G[x][i].len >= range) len = 1;
			else len = 0;

			if (dis[p] > dis[x] + len) {
				dis[p] = dis[x] + len;
				que.push(Node(p, dis[p]));
			}
		}
	}
	return dis[n];
}
int check(int mid) {
	int len = dijstra(1, mid);
	if (len >= k + 1) return 0;
	else return 1;
}
int main() {
	int be, en, len;
	scanf("%d%d%d", &n, &m, &k);
	for (int i = 0; i < m; i++) {
		scanf("%d%d%d", &be, &en, &len);
		insert(be, en, len);
		insert(en, be, len);
	}
	int l = 0;
	int r = 10000000;
	int mid;
	int flag = 0;
    
	while (r - l > 1) {
		mid = (r + l) / 2;
		if (check(mid)) {//往小了压
			r = mid;
		}
		else {
			l = mid ;
		}
	}
	if (r == 10000000) cout << "-1" << endl;
	else cout << l << endl;
	return 0;
}

  

寻找真正的热爱
原文地址:https://www.cnblogs.com/lesning/p/11695427.html