codevs 1021 玛丽卡(spfa)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了codevs 1021 玛丽卡(spfa)相关的知识,希望对你有一定的参考价值。

传送门

Description

麦克找了个新女朋友,玛丽卡对他非常恼火并伺机报复。

    因为她和他们不住在同一个城市,因此她开始准备她的长途旅行。

    在这个国家中每两个城市之间最多只有一条路相通,并且我们知道从一个城市到另一个城市路上所需花费的时间。

    麦克在车中无意中听到有一条路正在维修,并且那儿正堵车,但没听清楚到底是哪一条路。无论哪一条路正在维修,从玛丽卡所在的城市都能到达麦克所在的城市。

    玛丽卡将只从不堵车的路上通过,并且她将按最短路线行车。麦克希望知道在最糟糕的情况下玛丽卡到达他所在的城市需要多长时间,这样他就能保证他的女朋友离开该城市足够远。

编写程序,帮助麦克找出玛丽卡按最短路线通过不堵车道路到达他所在城市所需的最长时间(用分钟表示)。

Input

第一行有两个用空格隔开的数N和M,分别表示城市的数量以及城市间道路的数量。1≤N≤1000,1≤M≤N*(N-1)/2。城市用数字1至N标识,麦克在城市1中,玛丽卡在城市N中。

接下来的M行中每行包含三个用空格隔开的数A,B和V。其中1≤A,B≤N,1≤V≤1000。这些数字表示在A和城市B中间有一条双行道,并且在V分钟内是就能通过。

Output

输出文件的第一行中写出用分钟表示的最长时间,在这段时间中,无论哪条路在堵车,玛丽卡应该能够到达麦克处,如果少于这个时间的话,则必定存在一条路,该条路一旦堵车,玛丽卡就不能够赶到麦克处。

Sample Input

5 7

1 2 8

1 4 10

2 3 9

2 4 10

2 5 1

3 4 7

3 5 10

Sample Output

27

思路

  跑一遍spfa求出最短路并记录下路径,枚举最短路上的边删除,求出此时的最短距离,每次删除时,前一次的删除操作要恢复。更新最大值即可。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
const int maxn = 1005;
const int maxm = maxn*(maxn - 1)/2;
struct Edge
{
    int u,v,w,next;
} edge[maxm];
int head[maxm],vis[maxn],dis[maxn],prev[maxn];
int N,M,tot = 0,res;

void addedge(int u,int v,int w)
{
    edge[tot] = (Edge)
    {
        u,v,w,head[u]
    };
    head[u] = tot++;
}

int spfa(int x,int y)   //虽然玛丽卡在第N个城市,但是1-N的最短距离固定,
{                       // 所以我们可以从第1个城市出发,求出1-N的最短路 
    memset(dis,0x3f,sizeof(dis));
    memset(vis,0,sizeof(vis));
    queue<int>que;
    dis[1] = 0;
    que.push(1);
    vis[1] = 1;
    while (!que.empty())
    {
        int u = que.front();
        que.pop();
        vis[u] = 0;
        for (int i = head[u]; i != -1; i = edge[i].next)
        {
            int v = edge[i].v;
            if ((u == x && v == y) || (u == y && v == x))	continue;
            if (dis[u] + edge[i].w < dis[v])
            {
                dis[v] = dis[u] + edge[i].w;
                prev[v] = u;           //记录前驱(路径) 
                if (!vis[v])
                {
                    que.push(v);
                    vis[v] = 1;
                }
            }
        }
    }
    return dis[N];
}

int main()
{

    int u,v,w;
    memset(head,-1,sizeof(head));
    memset(prev,0,sizeof(prev));
    scanf("%d%d",&N,&M);
    for (int i = 0; i < M; i++)
    {
        scanf("%d%d%d",&u,&v,&w);
        addedge(u,v,w);
        addedge(v,u,w);
    }
    res = spfa(0,0);
    int tmp = N;
    queue<int>q;
    while (tmp)
    {
        q.push(tmp);
        tmp = prev[tmp];
    }
    while (q.size() > 1)
    {
        tmp = q.front();
        q.pop();
        res = max(res,spfa(tmp,q.front()));
    }
    printf("%d\n",res);
    return 0;
}

  

以上是关于codevs 1021 玛丽卡(spfa)的主要内容,如果未能解决你的问题,请参考以下文章

codevs 1021 玛丽卡(spfa)

spfa-codevs1021题解

Codevs1021题解---SPFA+路径记录

[codevs1021]玛丽卡

Codevs 1021 (玛丽卡)

codevs1021 玛丽卡