[codevs1021] 玛丽卡 优先队列优化dijkstra

1021 玛丽卡

时间限制: 2 s
空间限制: 128000 KB
题目描述 Description

    麦克找了个新女朋友,玛丽卡对他非常恼火并伺机报复。
    因为她和他们不住在同一个城市,因此她开始准备她的长途旅行。
    在这个国家中每两个城市之间最多只有一条路相通,并且我们知道从一个城市到另一个城市路上所需花费的时间。
    麦克在车中无意中听到有一条路正在维修,并且那儿正堵车,但没听清楚到底是哪一条路。无论哪一条路正在维修,从玛丽卡所在的城市都能到达麦克所在的城市。
    玛丽卡将只从不堵车的路上通过,并且她将按最短路线行车。麦克希望知道在最糟糕的情况下玛丽卡到达他所在的城市需要多长时间,这样他就能保证他的女朋友离开该城市足够远。
    编写程序,帮助麦克找出玛丽卡按最短路线通过不堵车道路到达他所在城市所需的最长时间(用分钟表示)。

输入描述 Input Description
第一行有两个用空格隔开的数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 Description
输出文件的第一行中写出用分钟表示的最长时间,在这段时间中,无论哪条路在堵车,玛丽卡应该能够到达麦克处,如果少于这个时间的话,则必定存在一条路,该条路一旦堵车,玛丽卡就不能够赶到麦克处。

样例输入 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

大水题,先找一遍最优路径并记录,依次封掉这条路上的所有边再找一遍,找出其中能到达的最大值。但我老是T,或许是写了假的dijkstra,后来看了正版的优先队列优化dijkstra才明白有一步不一样啊(那一步肯定剪枝了)

#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cstring>
const int INF = 0x3f3f3f3f;
const int N = 1005;
using namespace std;
int read() {
    int x = 0, f = 1;char ch = getchar();
    while( ch < '0' || ch > '9'){if(ch == '-')f=-1;ch=getchar();}
    while(ch>='0' && ch <='9'){x = x*10+ch-'0';ch = getchar();}
    return x*f;
}
int n,m,T,cnt,ans;
int mpre[N];
int last[N],pre[N],dis[N];
struct Node {
    int to,next,v;
}e[N*N];
struct node{
    int v,dis;
    friend bool operator < (node a,node c){return a.dis>c.dis;}
};
priority_queue<node>q;
void insert( int u, int v, int w ) {
    e[++cnt].to = v;e[cnt].next = last[u];last[u] = cnt;e[cnt].v=w;
}

int dijkstra(int yu, int pu) {
    memset(dis,0x3f,sizeof(dis));
    dis[1] = 0; q.push((node){1,0});
    while( !q.empty() ) {
        node now = q.top(); q.pop();
        if(dis[now.v]<now.dis)continue;//就是这一步,有了就不T了
        int u = now.v;
        for( int i = last[u]; i; i = e[i].next ){
            int v = e[i].to;
            if(( yu == u && pu == v)|| ( yu == v && pu == u )) continue;
            if( dis[u] + e[i].v < dis[e[i].to] ) {
                pre[v] = u;
                dis[v] = dis[u] + e[i].v;
                q.push((node){v,dis[v]});
            }
        }
    }
    return dis[n];
}

int main() {
    n = read();m = read();
    for( int i = 1; i <= m; i++ ) {
        int u = read(),v = read(),w1 = read();
        insert(u,v,w1);
        insert(v,u,w1);
    }
    int mis = dijkstra(0,0);
    int k = n;
    memcpy(mpre,pre,sizeof(mpre));
    while( k ){
        int mis = dijkstra(k,mpre[k]);
        if( mis != INF ) ans = max( mis, ans );
        k = mpre[k];
    }
    printf("%d\n",ans);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值