黑暗城堡(最短路径树)

黑暗城堡 

(castle.pas/c/cpp)

题目描述 

在顺利攻破 Lord lsp 的防线之后,lqr 一行人来到了 Lord lsp 的城堡下方。Lord lsp 黑化之后虽然拥有了强大的超能力,能够用意念力制造建筑物,但是智商水平却没怎么增加。现 lqr 已经搞清楚黑暗城堡有个房间,条可以制造的双向通道,以及每条通道的长度。 

lqr 深知 Lord lsp 的想法, 为了避免每次都要琢磨两个房间之间的最短路径,Lord lsp一定会把城堡修建成树形的; 但是,为了尽量提高自己的移动效率,Lord lsp 一定会使得城堡满足下面的条件:设 Di 为如果所有的通道都被修建, 号房间与第号房间的最短路径长度;而 Si 为实际修建的树形城堡中第号房间与第

号房间的路径长度,对于所有满足 1≤i≤N 的整数 i,有 Si = Di。为了打败 Lord lsplqr 想知道有多少种不同的城堡修建方案。于是 lqr  applepi 提出了这个问题。由于 applepi 要忙着出模拟赛,所以这个任务就交给你了。当然,你只需要输出答案对 231 – 1 取模之后的结果就行了。 

输入格式 

第一行有两个整数 N M 

之后行,每行三个整数 X L,表示可以修建之间的一条长度为的通道。 

输出格式 

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

样例输入 

3

3

 

1

2

2

1

3

1

2

3

1

样例输出 

2

数据范围与约定 

对于 30% 的数据,2≤N≤5M≤10 

对于 50%  的数据,满足条件的方案数不超过 10000 

对于 100%  的数据,2≤N≤1000N – 1≤M≤N(N – 1)/21≤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
",ans);
return 0;
}
原文地址:https://www.cnblogs.com/lmjer/p/9354625.html