城堡

//两遍spfa,第一遍找最短路,第二遍统计i到j的道路个数 
//根据乘法计数原理乘起来即可
#include<cstdio>
#include<queue>
#define MAX 100001
#define mod 2147483647
#define ll long long
#define M 499500
using namespace std;
queue<int> d;
int n,m,x,y,z,dist[1002],f[1002];
ll g[1001]={0ll},ans=1ll;
int be[1001],next[M*2],to[M*2],hf[M*2],cnt=0;
void add(int x,int y,int z){
    cnt++;
    next[cnt]=be[x];
    be[x]=cnt;
    to[cnt]=y;
    hf[cnt]=z;
}
void spfa(){
    for(int i=1;i<=n;i++) dist[i]=MAX;
    dist[1]=0;
    d.push(1);
    while(!d.empty()){
        int zz=d.front();
        f[zz]=0;
        d.pop();
        for(int i=be[zz];i;i=next[i])
            if(hf[i]+dist[zz]<dist[to[i]]){
                dist[to[i]]=hf[i]+dist[zz];
                if(!f[to[i]]){
                    f[to[i]]=1;
                    d.push(to[i]);
                }
            }
    }
}
void spfa2(){
    d.push(1);
    while(!d.empty()){
        int xz=d.front();
        d.pop();
        for(int i=be[xz];i;i=next[i])
            if(hf[i]+dist[xz]==dist[to[i]]){
                g[to[i]]++;
                if(g[to[i]]>=mod) g[to[i]]-=mod;
                if(!f[to[i]]){
                    d.push(to[i]);
                    f[to[i]]=1;
                }
            }
    }
    for(int i=1;i<=n;i++){
        ans=ans*g[i];
        if(ans>=mod) ans%=mod;
    }
    
}
int main(){
    freopen("castle.in","r",stdin);
    freopen("castle.out","w",stdout);
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        scanf("%d%d%d",&x,&y,&z);
        add(x,y,z);
        add(y,x,z);
    }
    spfa();
    g[1]=1ll;
    spfa2();
    printf("%I64d
",ans);
    fclose(stdin);
    fclose(stdout);
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/qingang/p/6059911.html