黑暗城堡

Description
在顺利攻破 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 还要忙着出模拟赛,所以这个任务就交给你了。当然,你只需要输出答案对 2^31 – 1 取模之后的结果就行了.

Input
第一行有两个整数 N 和 M。
之后 M 行,每行三个整数 X,Y 和 L,表示可以修建 X 和 Y 之间的一条长度为 L 的通道。
2≤N≤1000,N – 1≤M≤N(N – 1)/2,1≤L≤100

Output
输出一个整数,表示答案对 2^31 – 1 取模之后的结果。

Sample Input
3 3
1 2 2
1 3 1
2 3 1

Sample Output
2

首先求出单源最短路,然后考虑第i个点,我们可以枚举1~i-1个点,求出dis[j]+g[i][j]=dis[i]的点,然后使用乘法原理即可。由于第i个点不可能由那些dis比它大的点转移过来,因此我们要开始按dis排序

/*program from Wolfycz*/
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define inf 0x7fffffff
using namespace std;
typedef long long ll;
typedef unsigned int ui;
typedef unsigned long long ull;
inline int read(){
    int x=0,f=1;char ch=getchar();
    for (;ch<'0'||ch>'9';ch=getchar())  if (ch=='-')    f=-1;
    for (;ch>='0'&&ch<='9';ch=getchar())    x=(x<<1)+(x<<3)+ch-'0';
    return x*f;
}
inline void print(int x){
    if (x>=10)  print(x/10);
    putchar(x%10+'0');
}
const int N=1e3,M=1e6,MOD=0x7fffffff;
struct S1{
    #define ls (p<<1)
    #define rs (p<<1|1)
    #define fa (p>>1)
    struct node{
        int x,v;
        bool operator <(const node &a)const{return v<a.v;}
    }Q[N*50+10];
    int tot;
    void insert(int x,int v){
        Q[++tot]=(node){x,v};
        int p=tot;
        while (p!=1&&Q[p]<Q[fa])    swap(Q[p],Q[fa]),p=fa;
    }
    void Delete(){
        Q[1]=Q[tot--];
        int p=1,son;
        while (ls<=tot){
            if (rs>tot||Q[ls]<Q[rs])    son=ls;
            else    son=rs;
            if (Q[son]<Q[p])    swap(Q[p],Q[son]),p=son;
            else    break;
        }
    }
}Heap;
int pre[(M<<1)+10],now[N+10],child[(M<<1)+10],val[(M<<1)+10],tot;
int g[N+10][N+10],dis[N+10],ID[N+10];
bool vis[N+10];
void join(int x,int y,int z){pre[++tot]=now[x],now[x]=tot,child[tot]=y,val[tot]=z;}
void insert(int x,int y,int z){join(x,y,z),join(y,x,z);}
bool cmp(const int &x,const int &y){return dis[x]<dis[y];}
void Dijkstra(int x){
    memset(dis,63,sizeof(dis));
    Heap.insert(x,dis[x]=0);
    while (Heap.tot){
        int Now=Heap.Q[1].x;
        Heap.Delete();
        if (vis[Now])   continue;
        vis[Now]=1;
        for (int p=now[Now],son=child[p];p;p=pre[p],son=child[p]){
            if (dis[son]>dis[Now]+val[p]){
                dis[son]=dis[Now]+val[p];
                Heap.insert(son,dis[son]);
            }
        }
    }
}
int main(){
    int n=read(),m=read(),Ans=1;
    memset(g,63,sizeof(g));
    for (int i=1;i<=m;i++){
        int x=read(),y=read(),z=read();
        insert(x,y,z);
        g[y][x]=g[x][y]=min(g[x][y],z);
    }
    for (int i=1;i<=n;i++)  g[i][i]=0,ID[i]=i;
    Dijkstra(1);
    sort(ID+1,ID+1+n,cmp);
    for (int i=2;i<=n;i++){
        int res=0;
        for (int j=1;j<i;j++)
            if (dis[ID[j]]+g[ID[i]][ID[j]]==dis[ID[i]])
                res++;
        Ans=1ll*Ans*res%MOD;
    }
    printf("%d\n",Ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Wolfycz/p/9745781.html
今日推荐