1. 程式人生 > >瑪麗卡

瑪麗卡

題目描述

麥克找了個新女朋友,瑪麗卡對他非常惱火併伺機報復。

因為她和他們不住在同一個城市,因此她開始準備她的長途旅行。

在這個國家中每兩個城市之間最多隻有一條路相通,並且我們知道從一個城市到另一個城市路上所需花費的時間。

麥克在車中無意中聽到有一條路正在維修,並且那兒正堵車,但沒聽清楚到底是哪一條路。無論哪一條路正在維修,從瑪麗卡所在的城市都能到達麥克所在的城市。

瑪麗卡將只從不堵車的路上通過,並且她將按最短路線行車。麥克希望知道在最糟糕的情況下瑪麗卡到達他所在的城市需要多長時間,這樣他就能保證他的女朋友離開該城市足夠遠。

編寫程式,幫助麥克找出瑪麗卡按最短路線通過不堵車道路到達他所在城市所需的最長時間(用分鐘表示)。

輸入輸出格式

輸入格式:
第一行有兩個用空格隔開的數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;
}