zoukankan      html  css  js  c++  java
  • 次短路

    找了好半天才找到两个比较好理解的代码,暂时放到这,之后再来改。

    点击打开链接

    次短路[v]=最短路[u]+边[u,v] 或者 次短路[v]=次短路[u]+边[u,v] ,不同于普通最短路,我们需要维护两个数组:最短路+次短路。
    我这里采用 邻接表+dijkstra,不断更新最短路和次短路。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <vector>
    #include <queue>
    #define INF 0xfffffff
    using namespace std;
    
    struct Edge{
        int to,cost;
    };
    int n,r;
    vector<Edge> edge[5005];
    typedef pair<int,int> P;//first是最短距离,second是顶点编号
    int dis1[5005];//最短距离
    int dis2[5005];//次短距离
    
    void solve(){
        priority_queue<P,vector<P>,greater<P> > q;//递增的优先队列
        for(int i = 0; i <= n; i++){
            dis1[i] = INF;
            dis2[i] = INF;
        }
        dis1[1] = 0;
        q.push(P(0,1));
        while(!q.empty()){
            P p = q.top();
            q.pop();
            int v = p.second,d = p.first;
            if(dis2[v] < d)
                continue;
            for(int i = 0; i < edge[v].size(); i++){
                Edge &e = edge[v][i];
                int d2 = d + e.cost;
                //最短距离的更新,入队
                if(dis1[e.to] > d2){
                        printf("dis1[e.to]=%d > d2=%d ?
    ",e.to,d2);
                    swap(dis1[e.to],d2);
                    q.push(P(dis1[e.to],e.to));
                }
                //新的次短距离 应该 大于最短距离&&小于原来的次短距离
                if(dis2[e.to] > d2 && dis1[e.to] < d2){
                    printf("dis2[e.to]=%d > d2=%d ?
    ",e.to,d2);
                    dis2[e.to] = d2;
                    q.push(P(dis2[e.to],e.to));//入队
                }
            }
        }
        printf("%d
    ",dis2[n]);
    }
    
    int main(){
        while(~scanf("%d%d",&n,&r)){
            for(int i = 0; i <= n; i++)
                edge[i].clear();
            int u,v,cost;
            Edge tmp;
            for(int i = 0; i < r; i++){
                scanf("%d%d%d",&u,&v,&cost);
                tmp.to = v;tmp.cost = cost;
                edge[u].push_back(tmp);
                tmp.to = u;
                edge[v].push_back(tmp);
            }
            solve();
        }
        return 0;
    }
    

    点击打开链接http://blog.csdn.net/qq_21899803/article/details/52192736

    先算出每个点到1的最短路dis[i],再算出每个点到n点的最短路disr[i],然后枚举所有边,计算次短路dis[u]+disr[v]+edge[u][v]

    #include <cstdio>  
        #include <cstring>  
        #include <iostream>  
        #include <algorithm>  
        #include <cstring>  
        #include <queue>  
        #define MAXN 5010  
        #define MAXM 101000  
        #define INF 0x3f3f3f3f  
        using namespace std;  
          
        struct node  
        {  
            int v, w, next;  
        } edge[MAXM * 2];  
          
        int n, m, e, p, q;  
        int vis[MAXN], dis[MAXN], disr[MAXN], head[MAXN];  
          
        void insert(int x, int y, int w)  
        {  
            edge[e].v = y;  
            edge[e].w = w;  
            edge[e].next = head[x];  
            head[x] = e++;  
        }  
          
        void spfa(int src, int d[])  
        {  
            memset(vis, 0, sizeof(vis));  
            vis[src] = 1;  
            d[src] = 0;  
            queue<int> Q;  
            Q.push(src);  
            while(!Q.empty())  
            {  
                p = Q.front();  
                Q.pop();  
                vis[p] = 0;  
                for(int i = head[p]; i != -1; i = edge[i].next)  
                {  
                    int v = edge[i].v;  
                    int w = edge[i].w;  
                    if(d[v] > d[p] + w)  
                    {  
                        d[v] = d[p] + w;  
                        if(!vis[v])  
                        {  
                            vis[v] = 1;  
                            Q.push(v);  
                        }  
                    }  
                }  
            }  
        }  
          
        int main()  
        {  
            int a, b, c;  
            while(scanf("%d%d", &n, &m) != EOF)  
            {  
                e = 0;  
                memset(head, -1, sizeof(head));  
                memset(dis, 0x3f, sizeof(dis));  
                memset(disr, 0x3f, sizeof(dis));  
                for(int i = 0; i < m; i++)  
                {  
                    scanf("%d%d%d", &a, &b, &c);  
                    insert(a, b, c);  
                    insert(b, a, c);  
                }  
                spfa(1, dis);  
                spfa(n, disr);  
                int mini = dis[n];  
                int ans = INF;  
                for(int i = 1; i <= n; i++)  
                {  
                    for(int j = head[i]; j != -1; j = edge[j].next)  
                    {  
                        int v = edge[j].v;  
                        int w = edge[j].w;  
                        if(dis[i] + disr[v] + w > mini && dis[i] + disr[v] + w < ans)  
                            ans = dis[i] + disr[v] + w;  
                    }  
                }  
                printf("%d
    ",ans);  
            }  
            return 0;  
        }  


  • 相关阅读:
    闭包跟装饰器
    几个常见的面试题目
    函数的进阶
    python的生成器和迭代器
    Python的数据类型
    “随手记”开发记录day09
    “随手记”开发记录day08
    “随手记”开发记录day07
    “随手记”开发记录day06
    “随手记”开发记录day05
  • 原文地址:https://www.cnblogs.com/qie-wei/p/10160262.html
Copyright © 2011-2022 走看看