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 }