洛谷P1144-最短路计数-最短路变形

洛谷P1144-最短路计数

题目描述:

给出一个\(N\)个顶点\(M\)条边的无向无权图,顶点编号为\(1-N\)。问从顶点\(1\)开始,到其他每个点的最短路有几条。


思路:

\(Dijkstra\)的一个变形题目。

在跑\(Dijkstra\)松弛的时候,若dis[v] > dis[u] + 1那么res[v]=res[u],若dis[v] == dis[u] + 1那么res[v] += res[u],其中res[v]存储的是点\(1\)到点\(v\)的最短路的数量。这里用到了\(dp\)的思想。


AC代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <algorithm>

const int Maxn = 2000005;
const int MOD = 100003;
const int INF = 0x3f3f3f3f;

struct EDGE {
	int v, next;
} e[Maxn << 1];

struct Node {
	int pos, dis;

	Node(){}

	Node(int pos, int dis):pos(pos), dis(dis){}

	bool operator < (const Node &x) const {
		return dis > x.dis;
	}
};

int head[Maxn], tot = 1;
int res[Maxn], dis[Maxn], vis[Maxn];

void add(int u, int v) {
	e[tot].v = v;
	e[tot].next = head[u];
	head[u] = tot++;
}

void dijkstra(int s) {
	memset(dis, INF, sizeof dis);
	memset(vis, 0, sizeof vis);
	memset(res, 0, sizeof res);
	res[s] = 1;
	dis[s] = 0;
	std::priority_queue<Node>q;
	q.push(Node(s, 0));
	for (; !q.empty();) {
		int u = q.top().pos;
		q.pop();
		if (vis[u]) {
			continue;
		}
		vis[u] = true;
		for (int i = head[u]; i; i = e[i].next) {
			int v = e[i].v;
			if (dis[v] > dis[u] + 1) {
				dis[v] = dis[u] + 1;
				res[v] = res[u];
				q.push(Node(v, dis[v]));
			} else if (dis[v] == dis[u] + 1) {
				res[v] += res[u];
				res[v] %= MOD;
			}
		}
	}
}

void solve() {
	int nv, ne;
	scanf("%d %d", &nv, &ne);
	int u, v;
	for (int i = 0; i < ne; i++) {
		scanf("%d %d", &u, &v);
		add(u, v);
		add(v, u);
	}
	dijkstra(1);
	for (int i = 1; i <= nv; i++) {
		printf("%d\n", res[i] % MOD);
	}
}

int main() {
	solve();
	return 0;
}

posted @ 2021-02-06 18:00  牟翔宇  阅读(38)  评论(0编辑  收藏  举报