POJ3255--次短路

求1到N的次短路,到某个顶点v的次短路有两种可能,一是到其他某个顶点u的最短路+edge(u,v)二是到其他某个点u的次短路+edge(u,v);

因此在松弛的时候不仅要记录最短路,同时也要记录次短路

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
#include<cstring>
#include<string>
#include<queue>
#define INF 1e6
using namespace std;
const int maxn = 5005;
struct node
{
    int d,u;
    bool operator < (const node& rhs) const{
        return d > rhs.d;
    }
};
struct Edge
{
    int from,to,dist;
    Edge(int u,int v,int d):from(u),to(v),dist(d){}
};

int n,m;
vector<Edge> edges;//保存边的信息
vector<int> g[maxn];//保存的边在edges数组里的编号;
int d[maxn],d2[maxn];//最短距离,次短距离

void addedge(int from,int to,int dist)//跟刘汝佳学的。。
{
    edges.push_back((Edge){from,to,dist});
    edges.push_back((Edge){to,from,dist});
    int k = edges.size();
    g[from].push_back(k-2);
    g[to].push_back(k-1);
}

void dijkstra(int s)
{
    priority_queue<node> que;
    for(int i = 1; i <= n; ++i){ d[i] = d2[i]= INF;}
    d[s] = 0;

    que.push((node){0,s});
    while(!que.empty())
    {
        node x = que.top();que.pop();
        int u = x.u;
        if(d2[u] < x.d) continue;//如果次短距离比这个节点的d值还小。。说明没有更新的必要
        for(int i = 0; i < g[u].size(); ++i)
        {
            Edge& e = edges[g[u][i]];
            int p = x.d + e.dist;//待更新的值,从这个节点进行松弛操作,注意这里的x.d可能是最短距离也可能是次短距离。
            if(d[e.to] > p)
            {
                swap(d[e.to],p);//如果最短距离比这个P还大,那么要换一换这个值;这样可以省掉一些讨论
                que.push((node){d[e.to],e.to});
            }
            if(d2[e.to] > p&&d[e.to] < p)//这种p值介于最短与次短之间时要更新次短的距离。
            {
                d2[e.to] = p;
                que.push((node){d2[e.to],e.to});//次短也可能对以后的结果有影响,所以也加入队列。
            }
        }
    }
}
int main()
{
    //freopen("in","r",stdin);
    scanf("%d%d",&n,&m);
    int from,to,dist;
    for(int i = 0; i < m; ++i)
    {
        scanf("%d%d%d",&from,&to,&dist);
        addedge(from,to,dist);
    }
    dijkstra(1);
    cout<<d2[n]<<endl;
}

 

转载于:https://www.cnblogs.com/Norlan/p/4776006.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值