最短路径生成树的数量-黑暗城堡

时间:2024-11-18 07:43:04

信息学奥赛一本通T1486-黑暗城堡

时间限制: 2s 内存限制: 192MB 提交: 18 解决: 9

题目描述

知道黑暗城堡有 N 个房间,M 条可以制造的双向通道,以及每条通道的长度。
城堡是树形的并且满足下面的条件:
设 Di为如果所有的通道都被修建,第 i 号房间与第 1 号房间的最短路径长度;
而 Si 为实际修建的树形城堡中第 i 号房间与第 1号房间的路径长度;
要求对于所有整数 i(1≤i≤N),有 Si=Di成立。
你想知道有多少种不同的城堡修建方案。当然,你只需要输出答案对 231−1 取模之后的结果就行了。

输入格式

第一行为两个由空格隔开的整数 N,M;
第二行到第 M+1 行为3 个由空格隔开的整数 x,y,l:表示 x 号房间与 y 号房间之间的通道长度为 l。

输出格式

一个整数:不同的城堡修建方案数对 231−1 取模之后的结果。

样例输入

复制

4 6
1 2 1
1 3 2
1 4 3
2 3 1
2 4 2
3 4 1

样例输出

复制

6

提示

样例说明
一共有 4 个房间,6 条道路,其中 1 号和 2 号,1 号和 3 号,1 号和 4 号,2 号和 3 号,2 号和 4 号,3 号和 4 号房间之间的通道长度分别为 1,2,3,1,2,1。
而不同的城堡修建方案数对 231−1 取模之后的结果为 6。
数据范围:
对于全部数据,1≤N≤1000,1≤M≤N(N−1)/2,1≤l≤200。

 题解:

思路为先用dijkstra求得1到各点最短路径,再依次通过dis[j]=dis[u]+w[i],即若该点的dis值加上到下一个点的权值等于下一个点的dis值,那么到下一个点的路径数加一。最后将所以的点的路径数相乘取mod即答案,注意取模时千万别用2e31-1,这个会有问题,直接用整型,别用浮点型,至于为什么希望有大佬帮忙回复一下,感谢。

#include<bits/stdc++.h>
using namespace std;
typedef pair<int, int>PII;
const int N = 1010, M = N * N;
const long long mod = (1<<31)-1;
int h[N], e[M], ne[M], w[M], idx;
int dis[N];
int cnt[N];
bool st[N];
int n, m;

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

void dij()
{
	memset(dis, 0x3f, sizeof(dis));
	priority_queue<PII, vector<PII>, greater<PII>>q;
	q.push({ 0,1 });
	dis[1] = 0;
	while (q.size()) {
		auto t = q.top();
		q.pop();
		int u = t.second;
		if (st[u]) {
			continue;
		}
		st[u] = true;
		for (int i = h[u];~i;i = ne[i]) {
			int j = e[i];
			if (dis[j] > dis[u] + w[i]) {
				dis[j] = dis[u] + w[i];
				q.push({ dis[j],j });
			}
		}
	}

}
void get_cnt()
{
	for (int u = 1;u <= n;u++) {
		for (int i = h[u];~i;i = ne[i]) {
			int j = e[i];
			if (dis[j] == dis[u] + w[i]) {
				cnt[j]++;
			}
		}
	}
}
long long get_ans()
{
	long long ans = 1;
	cnt[1] = 1;
	for (int i = 1;i <= n;i++) {
		ans *= cnt[i];
		ans %= mod;
	}
	return ans;
}
int main()
{
	cin >> n >> m;
	memset(h, -1, sizeof h);
	for (int i = 1;i <= m;i++) {
		int a, b, c;
		cin >> a >> b >> c;
		add(a, b, c);
		add(b, a, c);
	}
	dij();
	get_cnt();
	long long res = get_ans();
	cout << res;
}