• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
jacklee404
Never Stop!
博客园    首页    新随笔    联系   管理    订阅  订阅
观光 拆点+Dijkstra(求次短路条数)

观光

题目

观光

思路

​ 最短路计数的拓展,和拯救大兵瑞恩一样,需要我们拆点,然后在对拆后的点进行Dijkstra, 将一个点的状态拆为最短距离和次短距离,同样可能存在环形依赖,我们可以跑Dijkstra来进行状态的递推,对比最短路计数,我们只需要在加一个次短路的状态,每次状态更新的时候,如果当前点能够更新最短距离树深层的节点,我们将他放入优先队列。设\(dist[x][1/0]\)分别表示从源点\(S \rightarrow s\)的最短距离和次短距离,那么我们考虑Dijkstra的时候进行状态的更新

\[dist[x][0] \ge val + w[i]: \newline (最短路退化为次短路) 将0的状态转移到1 \newline 更新dist[x][0]和cnt[x][0] \newline 两个都压入堆中更新下面的节点 \newline elif \space dist[x][0] = val + w[i]: \newline 只更新cnt[x][0], 由于dist没有更新不会更新下面的点 \newline elif \space dist[x][1] \ge val + w[i]: \newline 如果次短路可更新,用上面点的次短路更新该点的次短路 \newline elif \space dist[x][1] = val + w[i] \newline 更新cnt[x][1] \]

Code

#include <iostream>
#include <cstring>
#include <vector>
#include <queue>

using i64 = long long;

const int N = 1e3 + 10, M = 2e4 + 10;

int n, m, dist[N][2], cnt[N][2];

bool st[N][2];

int h[N], ne[M], w[M], e[M], idx;

int S, T;

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

struct Ver {
	int x, type, val;

	bool operator>(const Ver &b) const {
		return val > b.val;
	}
};

int dijkstra() {
	memset(dist, 0x3f, sizeof dist);
	memset(st, 0, sizeof st);
	memset(cnt, 0, sizeof cnt);

	std::priority_queue<Ver, std::vector<Ver>, std::greater<Ver>> h1;

	h1.push({S, 0, 0});

	dist[S][0] = 0;

	cnt[S][0] = 1;

	while (h1.size()) {
		Ver t = h1.top(); h1.pop();

		int x = t.x, type = t.type, val = t.val, count = cnt[x][type];

		if (st[x][type]) continue;

		st[x][type] = true;

		for (int i = h[x]; ~i; i = ne[i]) {
			int v = e[i];

			if (dist[v][0] > val + w[i]) {
				dist[v][1] = dist[v][0], cnt[v][1] = cnt[v][0];
				h1.push({v, 1, dist[v][1]});
				dist[v][0] = val + w[i], cnt[v][0] = count;
				h1.push({v, 0, dist[v][0]});
			} else if (dist[v][0] == val + w[i]) {
				cnt[v][0] += count;
			} else if (dist[v][1] > val + w[i]) {
				dist[v][1] = val + w[i], cnt[v][1] = count;
				h1.push({v, 1, dist[v][1]});
			} else if (dist[v][1] == val + w[i]) {
				cnt[v][1] += count;
			}
		}
	}

	int res = cnt[T][0];

	if (dist[T][0] + 1 == dist[T][1]) res += cnt[T][1];

	return res;
}

void solve() {
	memset(h, -1, sizeof h);
    idx = 0;
    
	std::cin >> n >> m;

	for (int i = 1; i <= m; i ++) {
		int a, b, l;

		std::cin >> a >> b >> l;

		add(a, b, l);
	}

	std::cin >> S >> T;

	std::cout << dijkstra() << "\n";
}

int main() {
	int _;

	std::cin >> _;

	while (_ --) {
		solve();
	}
}
posted on 2023-04-15 10:19  Jack404  阅读(16)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3