P1186 玛丽卡 - 最短路

->

题意:有n个点,m条无向边,问从1到n(或从n到1)的一个最长时间t,且满足删除任意一条边后,得到的最短路都小于等于这个时间t。

思路:可以发现只有删除最短路上的边时才会对答案有影响。因此我们枚举最短路上的每一条边,将它们删去后跑最短路,最后取max即为答案。注意删边后图要保证连通。

代码:

60pt:枚举每条边

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int N=1000+100,M=500000+10;
int n,m;
struct node{
    int to,nxt,w;
}e[M<<1];
int head[N],tot=1;
void add(int u,int v,int w){
    e[++tot]=(node){v,head[u],w};
    head[u]=tot;
}
queue<int>q;
bool vis[N];
int dis[N];
int SPFA(int edge){
    while(q.size()) q.pop();
    for(int i=1;i<=n;i++) {
        vis[i]=false;
        dis[i]=(1<<30);
    }
    dis[1]=0,vis[1]=true;
    q.push(1);
    while(q.size()){
        int u=q.front();q.pop();vis[u]=0;
        for(int i=head[u];i;i=e[i].nxt){
            int v=e[i].to;
            if(dis[v]>dis[u]+e[i].w){
                dis[v]=dis[u]+e[i].w;
                if(!vis[v]){
                    q.push(v);vis[v]=1;
                }
            }
        }
    }
    return dis[n];
}
int main() {
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        add(u,v,w);
        add(v,u,w);
    }
    int ans=SPFA(tot+233);
    for(int i=1;i<=tot;i++){
        int x=e[i].w;
        e[i].w=(1<<30); 
        int now=SPFA(i);
        e[i].w=x;
        if(now!=(1<<30)) ans=max(ans,now);
    }
    printf("%d",ans);
    return 0;
}

100pt:枚举最短路

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<queue>
 5 using namespace std;
 6 const int N=1000+100,M=500000+10;
 7 int n,m;
 8 struct node{
 9     int fro,to,nxt,w;
10 }e[M<<1];
11 int head[N],tot=1;
12 void add(int u,int v,int w){
13     e[++tot]=(node){u,v,head[u],w};
14     head[u]=tot;
15 }
16 queue<int>q;
17 bool vis[N];
18 int dis[N];
19 int pre[N];
20 //通过记录每个点的前驱来记录最短路路径 
21 bool f;
22 //标记是否为第一次SPFA,即是否要记录前驱 
23 void SPFA(){
24     while(q.size()) q.pop();
25     for(int i=1;i<=n;i++) {
26         vis[i]=false;
27         dis[i]=(1<<30);
28         //千万别像我把pre初始化了 
29     }
30     dis[n]=0,vis[n]=true;
31     q.push(n);
32     while(q.size()){
33         int u=q.front();q.pop();vis[u]=0;
34         for(int i=head[u];i;i=e[i].nxt){
35             int v=e[i].to;
36             if(dis[v]>dis[u]+e[i].w){
37                 if(!f) 
38                 //因为要求最初的最短路路径 
39                 //所以只有第一次最短路时才记录每个点的前驱 
40                     pre[v]=i;
41                 dis[v]=dis[u]+e[i].w;
42                 if(!vis[v]){
43                     q.push(v);vis[v]=1;
44                 }
45             }
46         }
47     }
48 }
49 int main() {
50     scanf("%d%d",&n,&m);
51     for(int i=1;i<=m;i++){
52         int u,v,w;
53         scanf("%d%d%d",&u,&v,&w);
54         add(u,v,w);
55         add(v,u,w);
56     }
57     SPFA();
58     f=true;
59     int ans=dis[1];
60     for(int i=pre[1];i;i=pre[e[i].fro]){
61         //枚举记录的最短路路径 
62         int x=e[i].w;
63         e[i].w=(1<<30);
64         SPFA();
65         e[i].w=x;//回溯 
66         if(dis[1]!=(1<<30)) //图要保证连通 
67             ans=max(ans,dis[1]);
68     }
69     printf("%d",ans);
70     return 0;
71 }

猜你喜欢

转载自www.cnblogs.com/Loi-Brilliant/p/9010577.html