• HDU——1874畅通工程续(Dijkstra与SPFA)


    畅通工程续

    Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 42616 Accepted Submission(s): 15785

    Problem Description
    某省自从实行了很多年的畅通工程计划后,终于修建了很多路。不过路多了也不好,每次要从一个城镇到另一个城镇时,都有许多种道路方案可以选择,而某些方案要比另一些方案行走的距离要短很多。这让行人很困扰。

    现在,已知起点和终点,请你计算出要从起点到终点,最短需要行走多少距离。

    Input
    本题目包含多组数据,请处理到文件结束。
    每组数据第一行包含两个正整数N和M(0< N< 200,0< M< 1000),分别代表现有城镇的数目和已修建的道路的数目。城镇分别以0~N-1编号。
    接下来是M行道路信息。每一行有三个整数A,B,X(0<=A,B< N,A!=B,0< X <10000),表示城镇A和城镇B之间有一条长度为X的双向道路。
    再接下一行有两个整数S,T(0<= S,T< N),分别代表起点和终点。

    Output
    对于每组数据,请在一行里输出最短需要行走的距离。如果不存在从S到T的路线,就输出-1.

    Sample Input
    3 3
    0 1 1
    0 2 3
    1 2 1
    0 2
    3 1
    0 1 1
    1 2

    Sample Output
    2
    -1

    用优先队列优化的真的可以减少不必要的操作。如果要完美打印路径的话把记录路径的数组改为结构体,储存距离和这个点的前驱点即pre。然后算完之后从终点往前用pre迭代寻找后反向打印即可。这个方法还适用于离散数学的Dijkstra标号法那道题。
    SPFA代码:

    #include<iostream>
    #include<algorithm>
    #include<cstdlib>
    #include<sstream>
    #include<cstring>
    #include<cstdio>
    #include<string>
    #include<deque>
    #include<stack>
    #include<cmath>
    #include<queue>
    #include<set>
    #include<map>
    using namespace std;
    typedef long long LL;
    #define INF 0x3f3f3f3f
    const int N=1010;
    int d[N];
    vector<pair<int,int> >edge[N];
    void init()
    {
        for (int i=0; i<N; i++)
        {
            edge[i].clear();
            d[i]=INF;
        }
    }
    
    int main(void)
    {
        int n,m,i,j,x,y,z;
        while (~scanf("%d%d",&n,&m))
        {
            init();
            for (i=1; i<=m; i++)
            {
                scanf("%d%d%d",&x,&y,&z);
                edge[x].push_back(make_pair(y,z));
                edge[y].push_back(make_pair(x,z));
            }
            priority_queue<pair<int,int> > Q;
            int s,t;
            scanf("%d%d",&s,&t);
            Q.push(make_pair(-d[s],s));
            d[s]=0;
            while (!Q.empty())
            {
                int now=Q.top().second;
                Q.pop();
                for (i=0; i<edge[now].size(); i++)
                {
                    int t=edge[now][i].first;
                    if(d[t]>d[now]+edge[now][i].second)
                    //若临时距离比永久距离短,则进行松弛操作,好比A->B->C   比A->C要短,则A到C的路径就改为A->C
                    {
                        d[t]=d[now]+edge[now][i].second;
                        Q.push(make_pair(-d[t],t));
                    }
                }
            }
            if(d[t]==INF)
                puts("-1");
            else
                printf("%d
    ",d[t]);
        }
        return 0;
    }

    Dijkstra代码(打印路径):

    #include<iostream>
    #include<algorithm>
    #include<cstdlib>
    #include<sstream>
    #include<cstring>
    #include<cstdio>
    #include<string>
    #include<deque>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<set>
    #include<map>
    using namespace std;
    #define INF 0x3f3f3f3f  
    typedef long long LL;
    struct info
    {
        int d;
        int pre;
    };
    const int N=1010;
    int n,m,s,t;
    info d[N];
    int inq[N];
    vector<pair<int,int> >vec[N];
    void init()
    {
        for (int i=0; i<N; i++)
        {
            d[i].d=INF;
            d[i].pre=-1;
            vec[i].clear();
            inq[i]=0;
        }
    }
    int main(void)
    {
        int i,j,k,ans,x,y,dx;
        while (cin>>n>>m)
        {
            init();
            for (i=0; i<m; i++)
            {
                cin>>x>>y>>dx;
                vec[x].push_back(make_pair(y,dx));
                vec[y].push_back(make_pair(x,dx));
            }
            cin>>s>>t;
            queue<int> q;
    
            q.push(s);
            d[s].d=0;
            inq[s]=1;
    
            while (!q.empty())
            {
                int now=q.front();
                q.pop();
                inq[now]=0;                         
                for (i=0; i<vec[now].size(); i++)   
                {
                    int v=vec[now][i].first;        
                    if(d[v].d>d[now].d+vec[now][i].second)/
                    {
                        d[v].pre=now;           
                        d[v].d=d[now].d+vec[now][i].second;
                        if(inq[v]==1)               
                            continue;
                        inq[v]=1;
                        q.push(v);                              
                    }    
                }
            }
            if(d[t].d==INF)
                cout<<"There is no such way"<<endl;
            else
            {
                stack<int> his;
                his.push(t);
                for (i=t; d[i].pre!=-1; i=d[i].pre)
                {       
                    his.push(d[i].pre);
                }
                while (1)
                {
                    cout<<his.top();
                    his.pop();
                    if(his.empty())
                        break;
                    else
                        cout<<"-->>";
                }
                cout<<"
    "<<"Total distance:"<<d[t].d<<'
    '<<endl;
            }    
        }
        return 0;
    }
  • 相关阅读:
    【NOIP2016提高A组集训第14场11.12】随机游走
    poj2378 树形DP
    简单博弈论总结加例题解析
    uva11426 欧拉函数应用
    poj3090欧拉函数求和
    lightOJ1370 欧拉函数性质
    hdu4497 正整数唯一分解定理应用
    hdu1215 正整数唯一分解定理应用
    lightoj 1236 正整数唯一分解定理
    素数筛两种方法
  • 原文地址:https://www.cnblogs.com/Blackops/p/5766385.html
Copyright © 2020-2023  润新知