码迷,mamicode.com
首页 > 其他好文 > 详细

洛谷P2832 行路难 分析+题解代码【玄学最短路】

时间:2018-02-21 22:20:37      阅读:174      评论:0      收藏:0      [点我收藏+]

标签:push   namespace   i++   定时   目的   输入   算法分析   开始   algo   

洛谷P2832 行路难 分析+题解代码【玄学最短路】


题目背景:

小X来到了山区,领略山林之乐。在他乐以忘忧之时,他突然发现,开学迫在眉睫

题目描述:

山区有n座山。山之间有m条羊肠小道,每条连接两座山,只能单向通过,并会耗费小X一定时间。

小X现在在1号山,他的目的是n号山,因为那里有火车站。

然而小X的体力是有限的。他每通过一条羊肠小道,就会变得更疲劳,导致他通过任意一条羊肠小道的时间都增加1。

输入格式:

第一行两个数,n,m

第2行到第m+1行,每行3个数A,B,C,表示A、B之间有一条羊肠小道,可以让小X花费C的时间从A移动到B

输出格式:

两行 第一行一个数T,表示小X需要的最短时间

第二行若干个数,用空格隔开,表示小X的移动路线

例:1 4 2 5表示:小X从1号山开始,移动到4号山,再到2号山,最后到5号山。

输入样例:

5 8
2 4 2
5 2 1
1 2 1
4 3 2
1 3 3
4 5 2
1 5 8
3 5 3

输出样例:

5 8
2 4 2
5 2 1
1 2 1
4 3 2
1 3 3
4 5 2
1 5 8
3 5 3


算法分析:

很明显这是一道最短路(这不是废话嘛)
不过这道题引入了一个疲劳度
乍一看似乎挺难
但其实只要在更新最短路的时候
记录当前被更新最短路的节点i之前已经走过了几节点
即我们以num[v]表示v之前已经走过了几个节点
num[v]=num[u]+1;
u为能使到达v的最短路更新的上一个中介点
所以我们只要在下一次以v为中介点判断是否能更新最短路时加上num[v]即可
其余就只剩SPFA的模板了


废话不多说,呈上蒟蒻代码

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<queue>
#include<cstring>
using namespace std;

int n,m;
struct node
{
    int v;
    int dis;
};
vector<node> map[1000010];
int d[1000010];
int num[1000010];//记录疲劳值的数组,初始全部为0
bool inq [1000010];
int pre[1000010];//记录最短路径

void print(int u)
{
    if(pre[u]==u)
    {
        cout<<u<<" ";
        return ;
    }
    
    print(pre[u]);
    cout<<u<<" ";
}

void SPFA()
{
    for(int i=1;i<=n;i++)
    pre[i]=i;
    memset(d,127,sizeof(d));
    queue<int> q;
    q.push(1);
    inq[1]=true;
    d[1]=0;
    
    while(!q.empty())
    {
        int u=q.front();
        inq[u]=false;
        q.pop();
        
        for(int j=0;j<map[u].size();j++)
        {
            int v=map[u][j].v;
            int dis=map[u][j].dis;
            
            if(d[u]+dis+num[u]<d[v])
            {
                d[v]=d[u]+dis+num[u];
                pre[v]=u;
                num[v]=num[u]+1;//**高亮**这里更新num[v]的疲劳值
                if(!inq[v])
                {
                    q.push(v);
                    inq[v]=true;
                }
            }
        }
    }
}


int main()
{
    cin>>n>>m;
    for(int i=1;i<=m;i++)
    {
        int s,t,dis;
        cin>>s>>t>>dis;
        map[s].push_back( (node) {t,dis});
    }
    
    SPFA();
    cout<<d[n]<<endl;
    print(n);
    return 0;
} 

其实就是在SPFA模板里多加了一行。。。
妥妥的 “提高+/省选-” 玄学最短路

洛谷P2832 行路难 分析+题解代码【玄学最短路】

标签:push   namespace   i++   定时   目的   输入   算法分析   开始   algo   

原文地址:https://www.cnblogs.com/niiick/p/8457526.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!