玛丽卡

Posted euplectella

tags:

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

题目描述

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

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

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

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

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

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

输入输出格式

输入格式:
第一行有两个用空格隔开的数N和M,分别表示城市的数量以及城市间道路的数量。1≤N≤1000,1≤M≤N 。城市用数字1-N1?N标识,麦克在城市11中,玛丽卡在城市N中。

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

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

输入输出样例

输入样例#1: 复制
5 7
1 2 8
1 4 10
2 3 9
2 4 10
2 5 1
3 4 7
3 5 10
输出样例#1: 复制
27
简化一下题目,就是求任意删掉一条边后的最短路的时间,难点其实就在于枚举删边,其实解决方法就是邻接链表加边时记录一下边的起点在第一遍跑最短路时,记录下哪条边接入该点,最后递归删边删掉最短路上的边,跑最短路。具体实现看代码,我也借鉴了网上dalao们的做法

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
inline int read(){
    int x = 0;int f = 1;char c = getchar();
    while(c<‘0‘||c>‘9‘){
        if(c == ‘-‘)f = -f ;
        c = getchar();
    }
    while(c<=‘9‘&&c>=‘0‘){
        x = x*10 + c - ‘0‘;
        c = getchar();
    }
    return x*f;
}
queue<int>que;
int p,n,m,ans;
const int maxn = 2000000;
struct edge{
    int from,to,v,s;
}e[maxn];
int flag[maxn],pre[maxn],head[maxn],dis[maxn],vis[maxn];
void add(int a,int b,int c){
    p++;
    e[p].from = head[a];
    e[p].to = b;
    e[p].v = c;
    e[p].s = a;//记录起点
    head[a] = p;
}
void spfa(int root,int nth){
    for(int i = 1; i<=n; i++)dis[i] = maxn;
  
    memset(vis,0,sizeof(vis));
    dis[root] = 0; vis[root] = 1;
    que.push(root); 
    while(!que.empty()){
        int f = que.front();
        vis[f] = 0; que.pop(); 
        //cout<<dis[n];
        for(int i = head[f]; i; i = e[i].from){
            int u = e[i].to;
            //if(!flag[u])continue;
        
            if(dis[u] > dis[f] + e[i].v&&!flag[i]){
                dis[u] = dis[f] + e[i].v;
                if(nth == 1)pre[u] = i;//记录连向该点的边
                if(!vis[u]){
                    que.push(u);
                    vis[u] = 1;
                }
            }
        }
    }
}
int main(){
    n = read(); m = read();
    for(int i = 1; i<=m; i++){
        int a,b,c;
        a = read(); b = read(); c = read();
        add(a,b,c);
        add(b,a,c);
    }
    //
    spfa(1,1);
    
    for(int i = pre[n]; i ; i = pre[e[i].s]){//递归枚举删边
        int old = e[i].v;
        e[i].v = maxn;
        spfa(1,2);
        e[i].v = old;
        ans = max(ans,dis[n]);
    }
    cout<<ans;
    
    return 0;
}













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

Luogu P1186 玛丽卡

P1186 玛丽卡

P1186 玛丽卡

洛谷 P1186 玛丽卡

P1186 玛丽卡 --- 最短路

玛丽卡