zoukankan      html  css  js  c++  java
  • 九度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
    ****************************************************************/



    编程算法爱好者。
  • 相关阅读:
    poj 3616 Milking Time
    poj 3176 Cow Bowling
    poj 2229 Sumsets
    poj 2385 Apple Catching
    poj 3280 Cheapest Palindrome
    hdu 1530 Maximum Clique
    hdu 1102 Constructing Roads
    codeforces 592B The Monster and the Squirrel
    CDOJ 1221 Ancient Go
    hdu 1151 Air Raid(二分图最小路径覆盖)
  • 原文地址:https://www.cnblogs.com/liangrx06/p/5083932.html
Copyright © 2011-2022 走看看