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

洛谷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模板里多加了一行。。。

妥妥的 “提高+/省选-” 玄学最短路

上一篇:Linux破解root密码


下一篇:SQLserver分页查询实例