• 九度OJ 1100:最短路径 (最短路径)


    时间限制:1 秒

    内存限制:32 兆

    特殊判题:

    提交:4185

    解决:619

    题目描述:

    N个城市,标号从0到N-1,M条道路,第K条道路(K从0开始)的长度为2^K,求编号为0的城市到其他城市的最短距离

    输入:

    第一行两个正整数N(2<=N<=100)M(M<=500),表示有N个城市,M条道路
    接下来M行两个整数,表示相连的两个城市的编号

    输出:

    N-1行,表示0号城市到其他城市的最短路,如果无法到达,输出-1,数值太大的以MOD 100000 的结果输出。

    样例输入:
    4 4
    1 2
    2 3
    1 3
    0 1
    样例输出:
    8
    9
    11
    来源:
    2010年上海交通大学计算机研究生机试真题

    思路:

    此题的路径长度很特殊,不能用普通的数值来表示。可以用数组或字符串的方式来表示路径长度,同时定义相应的大整数运算。

    但由于路径长度的特殊性,更简单的办法是求最小生成树,求的过程中顺便求得最短路径。

    我开始用的第一种方法,需要考虑的细节较多,出错了几次,后来用第二种方法AC的。


    代码:

    #include <stdio.h>
    #include <stdlib.h>
     
    int rank[100] ;//记录每个树的深度
    int pre[100];//记录每个点的父节点
    int d[100][100];//记录各对间的距离
     
    void initSet(int n)//初始化,将每个点的父节点设为自己,深度为1
    {
        int i;
        for(i=0; i<n; i++)
        {
            rank[i] = 1;
            pre[i] = i;
            d[i][i] = 0;
        }
    }
     
    int findSet(int x)//找到每个点的父节点,并将这个点的父节点设置为数的根节点
    {
        if(x != pre[x])
            pre[x] = findSet(pre[x]);
        return pre[x];
    }
     
    void unionSet(int a, int b)//合并树,
    {
        int x = findSet(a);
        int y = findSet(b);
        if(x == y)//如果两个节点的父节点(树的根节点)是同一个,无需合并,直接跳过
            return;
        if(rank[x] >= rank[y])
        {
            rank[x] += rank[y];
            pre[y] = x;
        }
        else
        {
            rank[y] += rank[y];
            pre[x] = y;
        }//不是同一个树的的节点,小树合并到大树
    }
     
    int mod(int a, int b)//取模
    {
        int ret = 1;
        while(b--)
            ret = (ret*a)%100000;
        return ret;
    }
     
    int main()
    {
        int n, m, dist;
        int x, y, a, b;
        int i, j, k;
        while(scanf("%d%d", &n, &m)!=EOF)
        {
            initSet(n);
            for(i=0; i<m; i++)
            {
                scanf("%d%d", &x, &y);
                a = findSet(x);
                b = findSet(y);
                if(a == b)//二者已在同一个连通分量,距离定是最小了
                    continue;
                dist = mod(2, i);//取模
                for(j=0; j<n; j++)//更新两个连通分量的各对经过中间对的距离
                {
                    if(a != findSet(j))
                        continue;
                    for(k=0; k<n; k++)
                    {
                        if(b != findSet(k))
                            continue;
                        d[j][k] = d[k][j] = (d[j][x]+dist+d[y][k])%100000;
                    }
                }
                unionSet(x, y);
            }
            x = findSet(0);
            for(i=1; i<n; i++)
                if(findSet(i) != x)
                    printf("-1
    ");
                else
                    printf("%d
    ", d[0][i]);
        }
    }  
    /**************************************************************
        Problem: 1100
        User: liangrx06
        Language: C
        Result: Accepted
        Time:10 ms
        Memory:952 kb
    ****************************************************************/



    编程算法爱好者。
  • 相关阅读:
    java集合
    struts2的OGNL表达式
    struts2 result type
    struts2在Action中访问WEB资源
    03异或^
    02自加自减运算机制
    原码,补码,反码
    Java基础50题test10—自由落体
    Java基础50题test9—求完数
    Java基础50题test8—输入数字求和
  • 原文地址:https://www.cnblogs.com/liangrx06/p/5083932.html
Copyright © 2020-2023  润新知