zoukankan      html  css  js  c++  java
  • 2010上交:最短路径

    题目描述:

    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
    思路:long long 存储路径长度将会发生溢出,所以我们采用高精度。与平时高精度表示不同的是:这次大数将用2进制数表示。
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<vector>
    using namespace std;
    const int MAXN=505;
    const int MOD=100000;
    struct Edge{
        int to;
        int mark[MAXN];
        Edge(){}
        Edge(int to,int w)
        {
            memset(mark,0,sizeof(mark));
            this->to=to;
            mark[w]=1;
        }
    };
    vector<Edge> mp[MAXN];
    int n,m;
    int d[MAXN][MAXN];
    int vis[MAXN];
    bool judge(int now,Edge e)
    {
        int to=e.to;
        int sum[MAXN]={0};
        for(int i=0;i<MAXN-1;i++)
        {
            int x=(d[now][i]+e.mark[i]+sum[i]);
            sum[i]=x%2;
            sum[i+1]+=x/2;
        }
        for(int i=MAXN-1;i>=0;i--)
        {
            if(d[to][i]>sum[i])
                return true;
            if(d[to][i]<sum[i])
                return false;
        }
        return false;
    }
    void sign(int now,Edge e)
    {
        int sum[MAXN]={0};
        for(int j=0;j<MAXN-1;j++)
        {
            int x=(d[now][j]+e.mark[j]+sum[j]);
            sum[j]=x%2;
            sum[j+1]+=x/2;
        }
        for(int j=0;j<MAXN;j++)
            d[e.to][j]=sum[j];
    }
    void spfa(int s)
    {
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<MAXN;j++)
            {
                d[i][j]=1;
            }
            vis[i]=0;
        }
        
        for(int i=0;i<MAXN;i++)
        {
            d[s][i]=0;
        }
        queue<int> que;
        que.push(s);
        vis[s]=1;
        while(!que.empty())
        {
            int now=que.front();que.pop();
            vis[now]=0;
            for(int i=0;i<mp[now].size();i++)
            {
                Edge e=mp[now][i];
                if(judge(now,e))
                {
                    sign(now,e);
                    if(!vis[e.to])
                    {
                        vis[e.to]=1;
                        que.push(e.to);
                    }
                }
            }
        }
        for(int i=1;i<n;i++)
        {
            int s=0;
            for(int j=0;j<MAXN;j++)
            {
                if(d[i][j]==1)
                {
                    s++;
                }
            }
            if(s==MAXN)
                printf("-1
    ");
            else
            {
                int res=0;
                int k=1;
                for(int j=0;j<MAXN;j++)
                {
                    if(d[i][j]==1)
                    {
                        res+=k;
                        res%=MOD;
                    }
                    k*=2;
                    k%=MOD;
                }
                printf("%d
    ",res%MOD);
            }
        }
    }
    int main()
    {
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            for(int i=0;i<n;i++)
                mp[i].clear();
            for(int i=0;i<m;i++)
            {
                int u,v;
                scanf("%d%d",&u,&v);
                mp[u].push_back(Edge(v,i));
                mp[v].push_back(Edge(u,i));
            }
            spfa(0);
        }
        return 0;
    }
  • 相关阅读:
    Socket
    属性的使用案例
    link.bat
    未命名 (2)
    解决wordpress3.5更新插件和主题失败的问题
    解除文件锁定(此文件来自其他计算机,可能被阻止以保护该计算机)
    String转换成Integer源码分析
    实战体会Java多线程编程精要
    JAVA进阶:一个简单Thread缓冲池的实现
    Java对象的序列化和反序列化实践
  • 原文地址:https://www.cnblogs.com/program-ccc/p/5372870.html
Copyright © 2011-2022 走看看