题目描述
你知道黑暗城堡有\(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\)取模以后的结果。node
题解:首先dij,求出1号点到其余点的最短距离。
而后扫描全部边,若是dis[v]==dis[u]+e[i].w,说明让v点的距离为给最短距离的路径又多了一条,因此,cnt[v]++;
最终结果就是全部点的cnt[]相乘。ios
#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; }