zoukankan      html  css  js  c++  java
  • 一本通1486:【例题1】黑暗城堡

    评测地点

    【题目描述】

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

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

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

    (S_i) 为实际修建的树形城堡中第$ i$ 号房间与第$ 1 $号房间的路径长度;

    要求对于所有整数 (i(1≤i≤N)),有$ S_i=D_i$ 成立。

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

    【输入】

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

    【输出】

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

    【输入样例】

    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}−1 $取模之后的结果为 (6)

    数据范围:

    对于全部数据,(1≤N≤1000,1≤M≤ dfrac{N(N-1)}{2},1≤l≤200。)

    【分析】

    先用(dijkstra)求出1号房间到每个房间的单源最短路径存储到(dis)数组中。把树形城堡看作以1为根的有根树。由题,若(x)(y)的根节点,(x、y)之间的通道长度为(z),则应该有:(dis[y]=dis[x]+z)。事实上,我们把满足题目要求的树结构,即对任意一对父子结点(x、y)都有上式成立的树结构,称为图的一棵最短路径生成树。与(Prim)算法类似,统计有多少结点(x)满足(dis[p]=dis[x]+e[x][p]),让(p)与其中任意一个x相连都符合题目要求。

    【注意】

    最短路径生成树:对于任意一对父子结点(x、y)均满足(dis[y]=dis[x]+e[x][y])的树结构称为图的一棵最短路径生成树;
    在宏定义中!! (2^{31-1}) 写为  ((1<<31)-1)  要加括号!! 要加括号!! 不然就会(wa)好多好多次了...
    然后,不要忘了给(e)数组初始化....不然就默认为0了..
    这题数据范围比较小,所以可以用邻接矩阵,不过这个是树,稀疏图,一般是用邻接表的。

    【代码】

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<iomanip>
    #include<cstdlib>
    #include<queue>
    #include<map>
    #include<set>
    #include<stack>
    #include<vector>
    #define ll long long
    using namespace std;
    inline ll read()
    {
       ll s=0,w=1;
       char ch=getchar();
       while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
       while(isdigit(ch)) s=s*10+ch-'0',ch=getchar();
       return s*w;
    }
    int n,m;
    ll dis[1010][1010],g[20000],cnt[20000];
    bool vis[2000000]={0};
    int main()
    {
        n=read(),m=read();
        for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)//1.预处理
        	if(i==j)
    			dis[i][j]=0;
        	else
    			dis[j][i]=dis[i][j]=1e18;
        for(int i=1,x,y,z;i<=m;i++)
        {
            x=read(),y=read(),z=read();
            if(dis[x][y]>z)
                dis[x][y]=dis[y][x]=z;//注意这一步判断
        }
        for(int i=1;i<=n;i++)
            g[i]=dis[1][i];
        for(int i=1;i<=n;i++)//2.用dijkstra算法求出一号房间到每个房间的最短路
        {
            ll minn=1e18,u;
            for(int j=1;j<=n;j++)
                if(!vis[j]&&minn>g[j])
                    minn=g[j],u=j;
            vis[u]=1;
            for(int j=1;j<=n;j++)
                if(g[j]>dis[u][j]+g[u])
                    g[j]=g[u]+dis[u][j];
        }
        ll ans=1;
        for(int i=1;i<=n;i++)//3.方案累加
            for(int j=1;j<=n;j++)
                if(i!=j&&g[j]==g[i]+dis[i][j])
    			cnt[j]++;
        for(int i=1;i<=n;i++)
            if(cnt[i])
            ans*=cnt[i],ans%=2147483647;
        printf("%lld",ans);
        return 0;
    }
    
  • 相关阅读:
    Mysql 库表
    Mysql (二)
    SQLAlchemy
    Mysql 测试题
    jquery
    抽屉 演示
    前端项目
    JavaScript
    Html Css  练习
    Pandas之DataFrame——Part 3
  • 原文地址:https://www.cnblogs.com/Xchu/p/11691871.html
Copyright © 2011-2022 走看看