洛谷P4568 分层图最短路

题意:n个点,m条双向边,给出起点终点,最多有k条边可以免费通过,求起点到终点的最短路

#include <iostream>
#include <cstdio>
#include <queue>
#include <algorithm>
#include <string.h>
using namespace std;

const int N = 10010;
const int M = 100010;
const int INF = 0x3f3f3f3f;

int n, m , t, l = 0;
int ss, st;
int last[N], pre[M], other[M], len[M];
int dis[N][15];
bool vis[N][15] = {false};

struct rec{
	int x, dis, use;
	bool operator < (const rec &a) const {
		return (a.dis < dis);
	} 
};

inline void read(int &x) {
	x = 0; bool flag = false; char ch;
	while (ch = getchar(), ch < '!');
	if (ch == '-') flag = true, ch = getchar();
	while (x = x * 10 + ch - '0', ch = getchar(), ch > '!');
	if (flag) x = -x;
}

void connect(int x, int y, int z) {
	l++;
	pre[l] = last[x];
	last[x] = l;
	other[l] = y;
	len[l] = z;
}

void dijkstra() {
	priority_queue<rec> que;
	
	memset(dis, 0x3f, sizeof(dis));
	//for (int i = 0; i <= t; i++) dis[ss][i] = 0;
	dis[ss][0] = 0;
	que.push(rec{ss, 0, 0});
	//
	while (!que.empty()) {
		rec cur = que.top();
		que.pop();
		if (vis[cur.x][cur.use]) continue;
		vis[cur.x][cur.use] = true;
		//
		int p, q;
		q = last[cur.x];
		while (q != 0) {
			p = other[q];
			if (dis[p][cur.use] > cur.dis + len[q]) {
				dis[p][cur.use] = cur.dis + len[q];
				que.push(rec{p, dis[p][cur.use], cur.use});
			}
			if ((cur.use < t) && (dis[p][cur.use + 1] > cur.dis)) {
				dis[p][cur.use + 1] = cur.dis;
				que.push(rec{p, dis[p][cur.use + 1], cur.use + 1});
			}
			q = pre[q];
		}
	}
}

int main () {
	read(n); read(m); read(t);
	read(ss); read(st);
	for (int i = 1; i <= m; i++) {
		int x, y, z;
		read(x); read(y); read(z);
		connect(x, y, z);
		connect(y, x, z);
	}
	dijkstra();
	int ans = INF;
	for (int i = 0; i <= t; i++) ans = min(ans, dis[st][i]);
	printf("%d\n", ans);
	return 0;
}

posted @ 2020-08-12 19:08  Eirlys  阅读(188)  评论(0编辑  收藏  举报