黑暗城堡(最短路径树)
黑暗城堡
(castle.pas/c/cpp)
题目描述
在顺利攻破 Lord lsp 的防线之后,lqr 一行人来到了 Lord lsp 的城堡下方。Lord lsp 黑化之后虽然拥有了强大的超能力,能够用意念力制造建筑物,但是智商水平却没怎么增加。现在 lqr 已经搞清楚黑暗城堡有 N 个房间,M 条可以制造的双向通道,以及每条通道的长度。
lqr 深知 Lord lsp 的想法, 为了避免每次都要琢磨两个房间之间的最短路径,Lord lsp一定会把城堡修建成树形的; 但是,为了尽量提高自己的移动效率,Lord lsp 一定会使得城堡满足下面的条件:设 Di 为如果所有的通道都被修建, 第 i 号房间与第 1 号房间的最短路径长度;而 Si 为实际修建的树形城堡中第 i 号房间与第
1 号房间的路径长度,对于所有满足 1≤i≤N 的整数 i,有 Si = Di。为了打败 Lord lsp,lqr 想知道有多少种不同的城堡修建方案。于是 lqr 向 applepi 提出了这个问题。由于 applepi 还要忙着出模拟赛,所以这个任务就交给你了。当然,你只需要输出答案对 231 – 1 取模之后的结果就行了。
输入格式
第一行有两个整数 N 和 M。
之后 M 行,每行三个整数 X,Y 和 L,表示可以修建 X 和 Y 之间的一条长度为 L 的通道。
输出格式
输出一个整数,表示答案对 231 – 1 取模之后的结果。
样例输入
3 |
3 |
|
1 |
2 |
2 |
1 |
3 |
1 |
2 |
3 |
1 |
样例输出
2
数据范围与约定
对于 30% 的数据,2≤N≤5,M≤10。
对于 50% 的数据,满足条件的方案数不超过 10000。
对于 100% 的数据,2≤N≤1000,N – 1≤M≤N(N – 1)/2,1≤L≤100。
题目要求源点到其余点的最短路径d[i],并且求树上路径s[i]等于d[i]的生成树
所以先求出最短路径d[i],并记录d[i[是哪个点的最短路径属性为v;
然后按长度大小进行排序,为了避免重复计数,,最后把满足d[x]=d[y]+w[i][j]的一个点一个点的往生成树之中加
根据乘法原理求出答案即可
#include<cstdio> #include<algorithm> #include<cstring> #include<queue> using namespace std; typedef long long ll; const int maxn=1010; const ll nil=(long long)1<<40-1; #define mod ((1<<31)-1) struct my{ int v,next; ll w; }; struct lmjer{ int v; ll w; }; struct node{ int u; ll w; bool operator<(const node &rhs)const{ return w>rhs.w; } }; int fa,adj[maxn],n,m; ll tu[maxn][maxn]; lmjer d[maxn]; bool done[maxn]; priority_queue<node>Q; my bian[maxn*maxn]; void myinsert(int u,int v,ll w){ bian[++fa].v=v; bian[fa].next=adj[u]; bian[fa].w=w; adj[u]=fa; } void dijkstra(int s){ for (int i=1;i<=n;i++) d[i].w=nil,d[i].v=i; d[s].w=0; node x; x.u=s; x.w=0; Q.push(x); while(!Q.empty()){ x=Q.top();Q.pop(); int u=x.u; if(done[u]) continue; done[u]=true; for (int i=adj[u];i;i=bian[i].next){ int v=bian[i].v; if(d[v].w>d[u].w+bian[i].w){ d[v].w=d[u].w+bian[i].w; x.u=v; x.w=d[v].w; Q.push(x); } } } } bool cmp(const lmjer a,const lmjer b){ return a.w<b.w; } int main(){ scanf("%d%d",&n,&m); memset(tu,10,sizeof(tu)); int u,v; ll w; for (int i=1;i<=m;i++){ scanf("%d%d%lld",&u,&v,&w); myinsert(u,v,w); myinsert(v,u,w); tu[u][v]=tu[v][u]=min(tu[u][v],w); } dijkstra(1); sort(d+1,d+1+n,cmp); int ans=1; for (int i=2;i<=n;i++){ ll temp=0; for (int j=1;j<i;j++){ int x=d[i].v,y=d[j].v; if(d[i].w==d[j].w+tu[x][y]) temp++; } ans=(long long)ans*temp%mod; } printf("%d\n",ans); return 0; }