• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
jacklee404
Never Stop!
博客园    首页    新随笔    联系   管理    订阅  订阅
关于最短路算法的拓扑序列

关于最短路算法的拓扑序列

最短路计数问题

题目

最短路计数

思路

我们考虑依赖方式(动态规划的思想):

1. 先求出**全局最小值**是多少

2. 再分别求出每个子集中**等于全局最小值**的元素个数

如果存在环形依赖关系的话,这样并不能求出最终的数量。

我们举例环形依赖问题:

image-20230414190733638

​ 小王欠小张100元,小张欠小刘100元,小刘欠小王100元,显然着三个人互不相欠,但是我们按照动态规划的思想,小王->小张->小刘 得出结论每个人互相欠100元,因为动规是将重叠子问题并为图论中的一个节点,在跑一个DAG的推导,如果存在环形依赖关系,\(f\)可能需要多次被推导。

​ 最短路树(拓扑图)满足\(dist[v] = dist[u] + w(u \rightarrow v)\). 即该节点被其前去节点所更新。

image-20230414191310597

​ 如果该图存在权重等于\(0\)的环,显然该图存在无穷多个最短路序列,如果该权重\(<0\)则不存在最短路。

​ 对\(BFS或Dijkstra\) 显然都满足每一次出队的点都是满足拓扑序的,对于\(SPFA\)算法每次出队的时候由于该点的最短距离并不能被确定,我们并不能求出最短路的拓扑序。但是如果存在负权的话我们并不能使用Dijkstra,这时候需要使用SPFA算法先把最短路径求出来,然后再求最短路径树。

Code

#include <iostream>
#include <cstring>

using i64 = long long;

const int N = 1e5 + 10, M = 4e5 + 10, mod = 1e5 + 3;

int n, m;

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

int q[N], hh = 0, tt = -1;

int dist[N], cnt[N];

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

void bfs() {
	memset(dist, 0x3f, sizeof dist);

	q[++ tt] = 1;

	dist[1] = 0;

	cnt[1] = 1;

	while (hh <= tt) {
		int t = q[hh]; hh ++;

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

			if (dist[v] > dist[t] + 1) {
				dist[v] = dist[t] + 1;
				cnt[v] = cnt[t];
				q[++ tt] = v;
			} else if (dist[v] == dist[t] + 1) {
				cnt[v] = (cnt[v] + cnt[t]) % mod;	
			}
		}	
	}
}

int main() {
	memset(h, -1, sizeof h);

    scanf("%d%d", &n, &m);
	for (int i = 1; i <= m; i ++) {
		int x, y;

		scanf("%d%d", &x, &y);

		add(x, y);

		add(y, x);
	}

	bfs();

	for (int i = 1; i <= n; i ++) {
		printf("%d\n", cnt[i]);
	}
}
posted on 2023-04-14 19:52  Jack404  阅读(30)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3