loj黑暗城堡

黑暗城堡

题目描述
你知道黑暗城堡有\(N\)个房间,M 条可以制造的双向通道,以及每条通道的长度。
城堡是树形的并且满足下面的条件:
\(D_i\)为如果所有的通道都被修建,第i号房间与第1号房间的最短路径长度;
\(S_i\)为实际修建的树形城堡中第i号房间与第1号房间的路径长度;
要求对于所有整数\(i(1<= i <= N)\),有\(S_i = D_i\)成立。
你想知道有多少种不同的城堡修建方案。当然,你只需要输出答案对\(2 ^ {31} - 1\)取模之后的结果就行了。
输入格式
第一行为两个由空格隔开的整数 ;
第二行到第n + 1行为3个由空格隔开的整数x,y,l:表示x号房间与y号房间之间的通道长度为l。
输出格式
一个整数:不同的城堡修建方案数对\(2 ^ {31} - 1\)取模之后的结果。

题解:首先dij,求出1号点到其他点的最短距离。
然后扫描所有边,如果dis[v]==dis[u]+e[i].w,说明让v点的距离为给最短距离的路径又多了一条,所以,cnt[v]++;
最终结果就是所有点的cnt[]相乘。

#include <cstdio>
#include <iostream>
#include <queue> 
#define orz cout << "AK IOI"

using namespace std;
const int maxn = 1010;
const int maxm = 500010;
const int mod = 2e31 - 1;

inline int read()
{
	int x = 0, f = 1;
	char ch = getchar();
	while (ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
	while (ch >= '0' && ch <= '9') {x = x * 10 + ch - '0';ch = getchar();}
	return x * f;
}
int n, m, dis[maxn], vis[maxn], cnt[maxn];
long long ans = 1;
struct edge{
	int u, v, w, nxt;
}e[maxm << 1];
int head[maxn], js;
void add(int u, int v, int w)
{
	e[++js].u = u;
	e[js].v = v;
	e[js].w = w;
	e[js].nxt = head[u];
	head[u] = js;
}
struct node{
	int w, now;
	bool operator < (const node &x)const
	{
		return w > x.w;
	}
};
priority_queue<node> q;
void dijkstra(int s)
{
	for(int i = 1; i <= n; i++)
	dis[i] = 0x7fffffff;
	dis[s] = 0;
	q.push((node{0, s}));
	while(!q.empty())
	{
		node t = q.top();
		q.pop();
		int u = t.now;
		if(vis[u]) continue;
		vis[u] = 1;
		for(int i = head[u]; i; i = e[i].nxt)
	    {
	    	int v = e[i].v;
	    	if(dis[v] > dis[u] + e[i].w)
	    	{
	    		dis[v] = dis[u] + e[i].w;
				q.push((node{dis[v], v})); 
			}
		}
	}
}
int main()
{
    n = read(), m = read();
    for(int i = 1; i <= m; i++)
    {
    	int u = read(), v = read(), w = read();
    	add(u, v, w);
    	add(v, u, w);
	}
	dijkstra(1);
	/*for(int i = 1; i <= n; i++)
	printf("%d ",dis[i]);*/
	for(int i = 1; i <= n; i++)
	   for(int j = head[i]; j; j = e[j].nxt)
	   {
	   	  int v = e[j].v;
	  	  if(dis[v] == dis[i] + e[j].w) 
		  cnt[v]++;
	   } 
	for(int i = 2; i <= n; i++)
	ans = ans * cnt[i] % mod;
	printf("%lld",ans);
	return 0;
}
posted @ 2020-12-30 19:33  _程门立雪  阅读(112)  评论(0编辑  收藏  举报