• 黑暗城堡(最短路径树)


    黑暗城堡 

    (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;
    }
  • 相关阅读:
    2019-9-2-正则表达式30分钟入门教程
    2019-6-23-开源项目使用-appveyor-自动构建
    2019-8-29-dotnet-core-使用-sqlite-部署到-Centos-服务器
    2018-10-19-Roslyn-使用-Directory.Build.props-文件定义编译
    2019-4-29-dotnet-通过-WMI-获取系统安装软件
    2018-12-24-win10-uwp-求两个矩形相连的几何
    shell公共函数functions
    linux防火墙和SELinux
    ubuntu开启ssh
    文件夹操作
  • 原文地址:https://www.cnblogs.com/lmjer/p/9354625.html
Copyright © 2020-2023  润新知