POJ - 3255 次短路径

题意:给你无向带权图,求次短路径

 

题解:加一个次短路的数组,用于距记录源点到此点的次短路长度,注意初始化是源点到自己的次短路是极大值

   接着再使用dijkstra算法,它是每次选用现在连上(记录了)的点与其他点的最小权值的边去更新其他所有的点

   就是在dij的算法上进行简单的修改,需要修改的是每次最短路更新之后再更新次短路,但是保证更新的次短路大于记录的次短路并小于记录的最短路

 

#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
const int inf=1<<29;
const int maxn=200010;
struct Edge
{
    int v,val;
    Edge(int v,int val):v(v),val(val) {}
    bool operator < (const Edge &c)const//改写大顶堆成为小顶堆
    {
        return val>c.val;
    }
};
vector<Edge> vec[maxn];
int dis[maxn],secondis[maxn];//记录第二短路径
void init(int n)
{
    for(int i=0; i<=n; ++i)
    {
        vec[i].clear();
    }
}
void dijkstraSecond(int n,int s)
{
    priority_queue<Edge> pque;
    for(int i=0; i<=n; ++i)
    {
        dis[i]=inf;
        secondis[i]=inf;//注意初始化
    }
    //secondis[s]=0;//不能初始化
    dis[s]=0;
    pque.push(Edge(s,0));
    while(!pque.empty())
    {
        Edge disE=pque.top();
        pque.pop();
        if(secondis[disE.v]<disE.val)//注意次短路都失败了才不能加上这条路
            continue;
        for(int i=0; i<vec[disE.v].size(); ++i)
        {
            Edge endE=vec[disE.v][i];
            int disnow=disE.val+endE.val;//注意这儿不能用dis求
            if(dis[endE.v]>disnow)//松弛最短路
            {
                swap(dis[endE.v],disnow);//由于松弛次短路,所以这儿是交换两者
                pque.push(Edge(endE.v,dis[endE.v]));
            }
            if(secondis[endE.v]>disnow&&dis[endE.v]<disnow)//松弛次短路
            {
                secondis[endE.v]=disnow;
                pque.push(Edge(endE.v,secondis[endE.v]));
            }
        }
    }
}
int main()
{
    int n,m;
    while(~scanf("%d %d",&n,&m))
    {
        init(n);
        while(m--)
        {
            int u,v,c;
            scanf("%d %d %d",&u,&v,&c);
            vec[u].push_back(Edge(v,c));
            vec[v].push_back(Edge(u,c));
        }
        dijkstraSecond(n,1);
//        for(int i=1; i<=n; ++i)
//        {
//            printf("secondis[i]=%d\n",secondis[i]);
//        }
        printf("%d\n",secondis[n]);
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/zhuanzhuruyi/p/6815337.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值