P1186 玛丽卡

玛丽卡

洛谷链接

题目大意:

有n个节点m条边,有一条边无法经过,求出任意一条边无法经过时节点1到节点n的最短路径的最大值。

思路:

这个题乍一看,感觉和求次小生成树的思路差不多,都是先求出最优的,然后依次删除最优路线上的边,计算目标值。

所以我们可以用spfa遍历一遍,求出从节点1到节点n的最短路径,并在循环中记录下被循环到的节点的父亲节点是哪个。之后遍历每个节点,由于已经知道该节点的父节点是什么,所以我们可以直接用两个变量记录下这两个节点,然后进行spfa,如果有一条边上的两个节点正好是这两个节点,就跳过这条边,这样就实现了每次删除最优路线上的边了。

代码:

 1 #include<queue>
 2 #include<cstdio>
 3 #include<cstring>
 4 #define N 1010
 5 #define M 1000000
 6 using namespace std;
 7 queue<int>p;
 8 int next[M],to[M],dis[M],num,head[N],n,m,a,b,c,exist[N],px,py,d[N],f,pre[N],ans;
 9 void add(int false_from,int false_to,int false_dis){
10     next[++num]=head[false_from];
11     to[num]=false_to;
12     dis[num]=false_dis;
13     head[false_from]=num;
14 }
15 void spfa(){
16     for(int i=1;i<=n;++i){
17         exist[i]=0;
18         d[i]=42000000;
19     }
20     p.push(1);
21     exist[1]=1;
22     d[1]=0;
23     while(!p.empty()){
24         int u=p.front();
25         p.pop();
26         exist[u]=0;
27         for(int i=head[u];i;i=next[i]){
28             if((to[i]==px&&u==py)||(to[i]==py&&u==px))
29                 continue;
30             if(d[to[i]]>d[u]+dis[i]){
31                 d[to[i]]=d[u]+dis[i];
32                 if(!f)
33                     pre[to[i]]=u;
34                 if(!exist[to[i]]){
35                     exist[to[i]]=1;
36                     p.push(to[i]);
37                 }
38             }
39         }
40     }
41 }
42 int main(){
43     scanf("%d%d",&n,&m);
44     for(int i=1;i<=m;++i){
45         scanf("%d%d%d",&a,&b,&c);
46         add(a,b,c);
47         add(b,a,c);
48     }
49     spfa();
50     f=1;
51     for(int i=n;i;i=pre[i]){
52         px=i;
53         py=pre[i];
54         spfa();
55         if(d[n]!=42000000)
56             ans=max(ans,d[n]);
57     }
58     printf("%d",ans);
59     return 0;
60 }
View Code