zoukankan      html  css  js  c++  java
  • POJ 3463 Sightseeing (次短路)

    题意:求两点之间最短路的数目加上比最短路长度大1的路径数目

    分析:可以转化为求最短路和次短路的问题,如果次短路比最短路大1,那么结果就是最短路数目加上次短路数目,否则就不加。

    求解次短路的过程也是基于Dijkstra的思想。算法中用一个二维数组d[u][tag](tag=0代表最短路,1代表次短路)来记录最短路和次短路的长度,cnt[u][tag]记录二者的数目。所以每个点都有两个访问状态,一个是最短路已经确定,另一个是次短路已经确定,所以vis[u][tag]数组也是二维的。

    每次维护邻接点的状态时,有四种可能情况:

      1.最短路长度需要更新。此时还需判断次短路是否需要更新,若最短路不存在,则不用更新;若最短路存在,则用最短路覆盖次短路。

      2.最短路数目需要更新。传递过来的路径长度与当前最短路相等,那么数量要加上去。

      3.次短路长度需要更新。

      4.次短路数目需要更新。

    且算法可以用优先队列改善效率。

    #include<iostream>
    #include<stdio.h>
    #include<cstring>
    #include<queue>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    using namespace std;
    typedef int LL;
    const int maxn =1e3+5,maxm = 2e4+5;
    const LL INF =0x3f3f3f3f;
     LL dis[maxn][2];            //最短路和次短路长度
    struct Edge{
        int to,next;
        LL val;
    };
    struct Node{
        int u,tag;
        bool operator <(const Node &rhs) const {return dis[u][tag]>dis[rhs.u][rhs.tag];}
    };
    
    struct SPFA{
        int n,m,tot;
        Edge edges[maxm];
        int head[maxn];
        bool vis[maxn][2];
        int cnt[maxn][2];           //最短路和次短路条数
    
        void init(int n){
            this->n = n;
            this->tot=0;
            memset(head,-1,sizeof(head));
        }
        void Addedge(int u,int v ,LL dist){
            edges[tot].to = v;
            edges[tot].val = dist;
            edges[tot].next = head[u];
            head[u] = tot++;
        }
        void spfa(int s){
            for(int i=0;i<=n;++i){
                dis[i][0]=INF,cnt[i][0]=0;
                dis[i][1]=INF,cnt[i][1]=0;
                vis[i][0]=vis[i][1]=false;   
            }
            dis[s][0]=0,cnt[s][0]=1;
            priority_queue<Node> Q;
            Q.push((Node){s,0});
            while(!Q.empty()){
                Node x =Q.top();Q.pop();
                int u = x.u,tag = x.tag;
                if(vis[u][tag]) continue;
                vis[u][tag] = true;
                for(int i=head[u];~i;i=edges[i].next){
                    int v =edges[i].to,w =edges[i].val;
                    int tmp = dis[u][tag] + w;
                    if(dis[v][0]>tmp) {      //需要更新最短路
                        if(dis[v][0]!=INF){     //将次短路覆盖
                            dis[v][1] = dis[v][0];
                            cnt[v][1] = cnt[v][0];
                            Q.push((Node){v,1});
                        }
                        dis[v][0]=tmp;
                        cnt[v][0]=cnt[u][tag];
                        Q.push((Node){v,0});
                    }
                    else if(dis[v][0]==tmp){        //最短路长度不变,数量增加
                        cnt[v][0]+=cnt[u][tag];
                    }
                    else if(dis[v][1]>tmp){         //次短路长度改变
                        dis[v][1] = tmp;
                        cnt[v][1] = cnt[u][tag];
                        Q.push((Node){v,1});
                    }
                    else if(dis[v][1]==tmp){        //次短路长度不变,数量增加
                        cnt[v][1]+=cnt[u][tag];
                    }
                }
            }
        }
    }G;
    
    #define LOCAL
    int main()
    {
        #ifdef LOCAL
            freopen("in.txt","r",stdin);
            freopen("out.txt","w",stdout);
        #endif
        int T,N,M,u,v, s,t;
        LL tmp;
        scanf("%d",&T);
        while(T--){
            scanf("%d%d",&N,&M);
            G.init(N);
            for(int i=1;i<=M;++i){
                scanf("%d%d%d",&u,&v,&tmp);
                G.Addedge(u,v,tmp);
            }
            scanf("%d%d",&s,&t);
            G.spfa(s);
            if(dis[t][1]==dis[t][0]+1) 
                G.cnt[t][0]+=G.cnt[t][1];
            printf("%d
    ",G.cnt[t][0]);
        }
        return 0;
    }
    为了更好的明天
  • 相关阅读:
    Thread.join
    Thread.yield
    线程的生命周期
    HashMap底层原理
    Web Services
    Struts2框架
    hibernate乐观锁实现原理
    Hibernate框架
    oracle exp 无法导出空表
    linux 远程复制文件或文件夹
  • 原文地址:https://www.cnblogs.com/xiuwenli/p/9353592.html
Copyright © 2011-2022 走看看