• [loj10064] 黑暗城堡


    #10064. 「一本通 3.1 例 1」黑暗城堡

    内存限制:512 MiB 时间限制:1000 ms 标准输入输出
    题目类型:传统    评测方式:文本比较
    上传者: 1bentong
    提交    提交记录    统计    讨论    测试数据
     

    题目描述

    你知道黑暗城堡有 N 个房间,M 条可以制造的双向通道,以及每条通道的长度。

    城堡是树形的并且满足下面的条件:

    设 Di 为如果所有的通道都被修建,第 i 号房间与第 1 号房间的最短路径长度;

    而 Si​​ 为实际修建的树形城堡中第 i 号房间与第 1 号房间的路径长度;

    要求对于所有整数 i (1iN),有 Si=Di​​ 成立。

    你想知道有多少种不同的城堡修建方案。当然,你只需要输出答案对 2^31 取模之后的结果就行了。

    输入格式

    第一行为两个由空格隔开的整数 N,M;

    第二行到第 M+1 行为 3 个由空格隔开的整数 x,y,l:表示 号房间与 y 号房间之间的通道长度为 l

    输出格式

    一个整数:不同的城堡修建方案数对 2^31 取模之后的结果。

    样例

    样例输入

    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。

    而不同的城堡修建方案数对 2^31 取模之后的结果为 6

    数据范围与提示

    对于全部数据,1≤N≤10001≤M≤N(N−1)/21≤l≤200

    题意:

    求一个无向图中最短路径树的棵数。

    最短路径树的定义:

    选出$N-1$条边组成一棵树,对于给定的源点$S$,

    若任何点$u$均满足在原图上$S$到点$u$的最短路$dis(u)$等于在这棵树上$S$到$u$的最短路$disnew(u)$,

    则这棵树是一棵最短路径树。

    猜了个结论,然后写了。错了。发现输入写错了。

    (千万不要把连边读入写成$add(read(),read(),read())$,这玩意好像是反着读进来的)

    改了输入,$A$了。

    ……

    一个简单的性质:两棵有标号的树互不相同当且仅当存在一个点u在两棵树中的$fa(u)$不同。

    考虑生成一棵最短路径树的方法,只需要在$dis(v)>dis(u)+e(u,v)$(即发生更新)时记录$fa(v)=u$,

    最后按父子关系把树连起来即可。由于每个点都有且仅有一个$fa$,可以证明这一定是一棵树。

    我们发现,若出现一个$v$使得$dis(v)=dis(u)+e(u,v)$,$fa(v)$便有两种选择,任取一种均合法。

    推广开来,当出现$N$个$dis(v)=dis(u)+e(u,v)$时,$fa(v)$便有$N+1$种选择,任取一种均合法。

    (由于$dis(v)=dis(u)+e(u,v)$这样的状态不会影响最短路算法的运行,所以$fa(v)$取何值都不会对其他点产生影响)

    既然每个点互不影响,我们就可以直接运用乘法原理把每个$fa(v)$的选择数乘起来得到答案。

    显然$fa(v)$的选择数就是满足$dis(v)=dis(u)+e(u,v)$的u的数目(这不是S到v的最短路径数),打板即可。

    代码:

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<queue>
    
    using namespace std;
    #define MAXN 100005
    #define MAXM 1000005
    #define mod 0x7fffffff
    #define ll long long
    
    ll hd[MAXN],to[MAXM<<1],cnt;
    ll nxt[MAXM<<1],cst[MAXM<<1];
    struct node{
        ll u,w;
        bool operator<(const node b)const
            {return w>b.w;}
    };
    ll dis[MAXN],ans[MAXN];
    bool vis[MAXN];
    inline ll read(){
        ll x=0,f=1;
        char c=getchar();
        for(;!isdigit(c);c=getchar())
            if(c=='-')
                f=-1;
        for(;isdigit(c);c=getchar())
            x=x*10+c-'0';
        return x*f;
    }
    
    inline void addedge(ll u,ll v,ll w){
        to[++cnt]=v,cst[cnt]=w,nxt[cnt]=hd[u],hd[u]=cnt;
        to[++cnt]=u,cst[cnt]=w,nxt[cnt]=hd[v],hd[v]=cnt;
        return;
    }
    
    inline void Dijkstra(ll s){
        memset(dis,127,sizeof(dis));
        priority_queue<node> q;
        q.push((node){s,0}); 
        ans[1]=1;dis[s]=0;
        while(!q.empty()){
            node tp=q.top();q.pop();
            if(vis[tp.u]) continue;
            vis[tp.u]=1;
            for(ll i=hd[tp.u];i;i=nxt[i]){
                ll v=to[i],w=cst[i];
                if(dis[v]>tp.w+w){
                    ans[v]=1,dis[v]=tp.w+w;
                    q.push((node){v,dis[v]});
                }
                else if(dis[v]==tp.w+w) ans[v]++;
            }
        }
        return;    
    }
    
    int main(){
        ll N=read(),M=read(),num=1;
        for(ll i=1;i<=M;i++){
            ll u=read(),v=read(),w=read();
            addedge(u,v,w);
        }
        Dijkstra(1);
        for(ll i=1;i<=N;i++) num*=ans[i]%mod,num%=mod;
        printf("%lld
    ",num%mod);
        return 0;
    }
  • 相关阅读:
    图算法之广度优先遍历
    图形算法之深度优先遍历
    list下SORT排序方法使用
    Linux使用curl进行接口测试
    Template方法应用
    profile[计算方法耗时模块]用法
    性能测试的实施及总结(二)
    yum源配置
    Dockerfile文件
    Docker的Image与Container
  • 原文地址:https://www.cnblogs.com/YSFAC/p/9851837.html
Copyright © 2020-2023  润新知