其他分享
首页 > 其他分享> > 最短路计数:在有重边和自环的情况下(BFS和Dijkstra分析)

最短路计数:在有重边和自环的情况下(BFS和Dijkstra分析)

作者:互联网

题1:初级最短路计数

洛谷1144 :无边权、无向图(可能有重边和自环)

算法分析:

这题的数据规模很大,我们得用邻接表存储,一开始我还傻不拉几的想怎么去重边和自环呢……其实重边和自环也要累计到最短路计数里边去。

由于这个题是没有边权的(也就是说,边权为 1)那么我自然想到一种简单的求最短路的办法:BFS。求BFS好办,那怎样最短路计数呢?

我们可以开辟一个数组:dep[]来记录到达每个点的深度,如果下次我们碰到一条路(因为第一次到达这个点的时候已经被标记数组标记,所以下次是到达不了这个点的!)但是我们可以到达这个点的上一个点,因为路径的不同,上一个点一定没有被标记!!

所以我们每次都去检查,上一个点的到达深度是不是+1就会等于当前的点。如果是的,那么就可以根据上一个点来到达当前的点,所以上一个点的最短路径计数就需要累计到当前的点的最短路计数上去!

AC代码:

#include <cstdio>
#include <vector>
#include <queue>
using namespace std;

const int maxn = 1e6 + 5, mod = 100003;
vector<int> G[maxn];
int n, m, a, b, vis[maxn], dep[maxn], cnt[maxn];
int main(){
	scanf("%d %d", &n, &m);
	while(m--){
		scanf("%d %d", &a, &b);
		G[a].push_back(b);
		G[b].push_back(a);
	}
	cnt[1] = 1, vis[1] = 1;
	queue<int> q;
	q.push(1);
	while(!q.empty()){
		int Now = q.front(); q.pop();
		for(int i = 0;i < (int)G[Now].size();++i){
			int Next = G[Now][i];
			if(!vis[Next]){
				vis[Next] = 1;
				dep[Next] = dep[Now] + 1;
				q.push(Next);
			}
			if(dep[Next] == dep[Now] + 1)
				cnt[Next] = (cnt[Next] + cnt[Now]) % mod; 
			// 每次碰到都累计上一个节点的计数,相当于上一个节点的计数乘以上一个节点到当前节点的重边数目 
		}
	}
	for(int i = 1;i <= n;++i)
		printf("%d\n", cnt[i] % mod);
	return 0;
}

题2:高级的最短路计数

洛谷:1608 这题最好还是用Dijkstra做

这题我用SPFA也做了,只想说,咱不去遭那个罪受

算法分析:

真的很简单了,如果做了上面那个题的话!
如果这个最短路更新, 当前点的最短路计数自然就是和上一个点一样(因为这对于当前点和上一个点来说,是唯一的路径!)

AC代码:

#include <cstdio>
#include <vector>
#include <queue>
using namespace std;

const int maxn = 2005, inf = 0x3f3f3f3f;
int n, m, a, b, c, dis[maxn], cnt[maxn], G[maxn][maxn], vis[maxn];
void Dijkstra(){
	for(int i = 1;i <= n;++i)
		dis[i] = inf;
	dis[1] = 0, cnt[1] = 1;// 这个 cnt[1] = 1 必须初始化!!! 
	for(int i = 0;i < n;++i){
		int u = 0;
		for(int j = 1;j <= n;++j)
			if(!vis[j] && (!u || dis[u] > dis[j]))
				u = j;
		vis[u] = 1;
		for(int k = 1;k <= n;++k){
			if(!G[u][k] || vis[k])	continue;
			if(dis[k] > dis[u] + G[u][k]){
				dis[k] = dis[u] + G[u][k];
				cnt[k] = cnt[u];
			}
			else if(dis[k] == dis[u] + G[u][k])
				cnt[k] += cnt[u];
		}
	} 
}

int main(){
	int cnt_n = 0;
	scanf("%d %d", &n, &m);
	while(m--){
		scanf("%d %d %d", &a, &b, &c);
		if(G[a][b] > c || !G[a][b])
			G[a][b] = c;
	}
	Dijkstra();
	if(dis[n] < inf)
		printf("%d %d", dis[n], cnt[n]);
	else
		printf("No answer");
	return 0;
} 
算法小弱 发布了48 篇原创文章 · 获赞 9 · 访问量 2129 私信 关注

标签:cnt,int,Next,BFS,计数,Dijkstra,自环,maxn,dis
来源: https://blog.csdn.net/qq_44274276/article/details/104416562