观光 次最短路及次数

// 观光.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。

/*
https://www.acwing.com/problem/content/description/385/
“您的个人假期”旅行社组织了一次比荷卢经济联盟的巴士之旅。

比荷卢经济联盟有很多公交线路。

每天公共汽车都会从一座城市开往另一座城市。

沿途汽车可能会在一些城市(零或更多)停靠。

旅行社计划旅途从 S 城市出发,到 F 城市结束。

由于不同旅客的景点偏好不同,所以为了迎合更多旅客,旅行社将为客户提供多种不同线路。

游客可以选择的行进路线有所限制,要么满足所选路线总路程为 S 到 F 的最小路程,
要么满足所选路线总路程仅比最小路程多一个单位长度。

3463_1.png

如上图所示,如果 S=1,F=5,则这里有两条最短路线 1→2→5,1→3→5,长度为 6;有一条比最短路程多一个单位长度的路线 1→3→4→5,长度为 7。

现在给定比荷卢经济联盟的公交路线图以及两个城市 S 和 F,请你求出旅行社最多可以为旅客提供多少种不同的满足限制条件的线路。

输入格式
第一行包含整数 T,表示共有 T 组测试数据。

每组数据第一行包含两个整数 N 和 M,分别表示总城市数量和道路数量。

接下来 M 行,每行包含三个整数 A,B,L,表示有一条线路从城市 A 通往城市 B,长度为 L。

需注意,线路是 单向的,存在从 A 到 B 的线路不代表一定存在从 B 到 A 的线路,另外从城市 A 到城市 B 可能存在多个不同的线路。

接下来一行,包含两个整数 S 和 F,数据保证 S 和 F 不同,并且 S、F 之间至少存在一条线路。

输出格式
每组数据输出一个结果,每个结果占一行。

数据保证结果不超过 109。

数据范围
2≤N≤1000,
1≤M≤10000,
1≤L≤1000,
1≤A,B,S,F≤N
输入样例:
2
5 8
1 2 3
1 3 2
1 4 5
2 3 1
2 5 3
3 4 2
3 5 4
4 5 3
1 5
5 6
2 3 1
3 2 1
3 1 10
4 5 2
5 2 7
5 2 7
4 1
输出样例:
3
2
*/
#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>

using namespace std;

const int N = 1010, M = 10010;
int n, m, S, T;
int h[N], ne[M], e[M], w[M], idx;
int dist[N][2], cnt[N][2];
bool vis[N][2];

struct ELE {
	int id, type, dist;
	bool operator > (const ELE& O) const {
		return dist > O.dist;
	}
};

void add(int a, int b, int l) {
	e[idx] = b, w[idx] = l, ne[idx] = h[a], h[a] = idx++;
}

int dijkstra(int start, int en) {
	priority_queue<ELE, vector<ELE>, greater<ELE>> heap;
	dist[start][0] = 0;
	cnt[start][0] = 1;
	heap.push({ start,0,0 });

	while (heap.size()) {
		auto t = heap.top(); heap.pop();
		int id = t.id, type = t.type, distance = t.dist;
		if (vis[id][type]) continue;
		vis[id][type] = true;

		for (int i = h[id]; i != -1; i = ne[i]) {
			int j = e[i]; int d = w[i];
			if (dist[j][0] > distance + d) {
				dist[j][1] = dist[j][0], cnt[j][1] = cnt[j][0];
				heap.push({ j,1,dist[j][1] });
				dist[j][0] = distance + d, cnt[j][0] = cnt[id][type];
				heap.push({ j,0,dist[j][0] });
			}
			else if (dist[j][0] == distance + d) {
				cnt[j][0] += cnt[id][type];
				heap.push({ j,0,dist[j][0] });
			}
			else if (dist[j][1] > distance + d) {
				dist[j][1] = distance + d, cnt[j][1] = cnt[id][type];
				heap.push({ j,1,dist[j][1] });
			}
			else if (dist[j][1] == distance + d) {
				cnt[j][1] += cnt[id][type];
				heap.push({ j,1,dist[j][1] });
			}
		}
	}

	int res = cnt[en][0];
	if (dist[en][1] - 1 == dist[en][0]) res += cnt[en][1];
	return res;
}


void solve() {
	memset(h, -1, sizeof h);   idx = 0;
	memset(dist, 0x3f, sizeof dist);
	memset(cnt, 0, sizeof cnt);
	memset(vis, 0, sizeof vis);
	cin >> n >> m;
	for (int i = 0; i < m; i++) {
		int a, b, l; cin >> a >> b >> l;
		add(a, b, l);
	}
	cin >> S >> T;

	int ans = dijkstra(S, T);

	cout << ans << endl;
	return;
}


int main()
{
	int loop; cin >> loop;
	while (loop--) {
		solve();
	}


	return 0;
}

posted on 2025-04-10 15:28  itdef  阅读(7)  评论(0)    收藏  举报

导航