黑暗城堡(最短路)
黑暗城堡
题目描述
你知道黑暗城堡有N个房间,M条可以制造的双向通道,以及每条通道的长度。
城堡是树形的并且满足下面的条件:
设Di为如果所有的通道都被修建,第i号房间与第1号房间的最短路径长度;
而Si为实际修建的树形城堡中第i号房间与第1号房间的路径长度;
要求对于所有整数i(1≤i≤N),有Si=Di成立。
你想知道有多少种不同的城堡修建方案。当然,你只需要输出答案对2^{31}−1取模之后的结果就行了。
城堡是树形的并且满足下面的条件:
设Di为如果所有的通道都被修建,第i号房间与第1号房间的最短路径长度;
而Si为实际修建的树形城堡中第i号房间与第1号房间的路径长度;
要求对于所有整数i(1≤i≤N),有Si=Di成立。
你想知道有多少种不同的城堡修建方案。当然,你只需要输出答案对2^{31}−1取模之后的结果就行了。
输入描述:
输入格式
第一行为两个由空格隔开的整数N,M;
第二行到第M+1行为3个由空格隔开的整数x,y,l:表示x号房间与y号房间之间的通道长度为l。
输出描述:
一个整数:不同的城堡修建方案数对2^{31}−1取模之后的结果。
示例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−12^{31}-1231−1取模之后的结果为6。
备注:
对于全部数据,1≤N≤1000,1≤M≤N(N−1)/2,1≤l≤200。
题目思路
先求出每个点到1号房间的最短路径,然后搜索每个房间i的每条连接到j的通道。
如果这条通道使得dist[i]==dist[j]+map[i][j],就使cnt++,说明到这个房间并且是最短路有cnt种方案。
最后的答案就是每个cnt相乘取模。
这里我用堆优化的迪杰斯特拉求最短路
#include<bits/stdc++.h> #define ll long long #define ull unsigned long long #define mod 2147483647; using namespace std; typedef struct a { int dis; int num; bool operator < (struct a o) const{ if(o.dis<dis) return true; return false; } }E; E e[500100]; ll n,m,dist[1001],ans,cnu; vector<E> v[1001]; priority_queue<E> q; void dijie() { E e1; e1.dis = 0; e1.num = 1; dist[1] = 0; q.push(e1); while(!q.empty()) { int p = q.top().num; q.pop(); for(int i = 0;i<v[p].size();i++) { if(dist[v[p][i].num]>dist[p]+v[p][i].dis) { dist[v[p][i].num] = dist[p]+v[p][i].dis; e1.dis = dist[v[p][i].num]; e1.num = v[p][i].num; q.push(e1); } } } ans = 1; for(int i = 2;i<=n;i++) { cnu = 0; for(int j = 0;j<v[i].size();j++) { if(dist[v[i][j].num]+v[i][j].dis==dist[i]) cnu++; } ans = cnu*ans%mod; } } int main() { memset(dist,0x3f,sizeof(dist)); int c1,c2,c3; E e2; cin>>n>>m; for(int i = 0;i<m;i++) { scanf("%d%d%d",&c1,&c2,&c3); e2.dis = c3; e2.num = c2; v[c1].push_back(e2); e2.num = c1; v[c2].push_back(e2); } dijie(); cout<<ans; return 0; }
如果有不对的地方,还请各位大佬指正。