BZOJ 1726 [Usaco2006 Nov]Roadblocks第二短路:双向spfa次短路
Posted Leohh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 1726 [Usaco2006 Nov]Roadblocks第二短路:双向spfa次短路相关的知识,希望对你有一定的参考价值。
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1726
题意:
给你一个无向图,求次短路。
题解:
两种方法。
方法一:
一遍spfa,在spfa内维护最短路dis和次短路sec。
分三种情况:
(1)dis[now]可以更新dis[dest]。
(2)dis[now]不能更新dis[dest],但dis[now]可以更新sec[dest]。
(3)dis[now]不能更新dis[dest]和sec[dest],但sec[now]可以更新sec[dest]。
分别处理即可。
方法二:
双向spfa。
dis[i]表示从1到i的最短路,rev[i]表示从n到i的最短路。
枚举每条边。找出最大的,但是比dis[n]小的dis[i] + len + rev[dest]的值,即为答案。
AC Code(1):
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <vector> 5 #include <queue> 6 #define MAX_N 5005 7 8 using namespace std; 9 10 struct Edge 11 { 12 int dest; 13 int len; 14 Edge(int _dest,int _len) 15 { 16 dest=_dest; 17 len=_len; 18 } 19 Edge(){} 20 }; 21 22 int n,m; 23 int dis[MAX_N]; 24 int sec[MAX_N]; 25 bool vis[MAX_N]; 26 vector<Edge> edge[MAX_N]; 27 queue<int> q; 28 29 int get_front() 30 { 31 int now=q.front(); 32 q.pop(); 33 vis[now]=false; 34 return now; 35 } 36 37 void insert(int now) 38 { 39 if(vis[now]) return; 40 q.push(now); 41 vis[now]=true; 42 } 43 44 void spfa(int start) 45 { 46 memset(dis,0x3f,sizeof(dis)); 47 memset(sec,0x3f,sizeof(sec)); 48 memset(vis,false,sizeof(vis)); 49 insert(start); 50 dis[start]=0; 51 while(!q.empty()) 52 { 53 int now=get_front(); 54 for(int i=0;i<edge[now].size();i++) 55 { 56 Edge temp=edge[now][i]; 57 if(dis[temp.dest]>dis[now]+temp.len) 58 { 59 sec[temp.dest]=min(dis[temp.dest],sec[now]+temp.len); 60 dis[temp.dest]=dis[now]+temp.len; 61 insert(temp.dest); 62 } 63 else if(dis[temp.dest]<dis[now]+temp.len && sec[temp.dest]>dis[now]+temp.len) 64 { 65 sec[temp.dest]=dis[now]+temp.len; 66 insert(temp.dest); 67 } 68 else if(dis[temp.dest]==dis[now]+temp.len && sec[temp.dest]>sec[now]+temp.len) 69 { 70 sec[temp.dest]=sec[now]+temp.len; 71 insert(temp.dest); 72 } 73 } 74 } 75 } 76 77 void read() 78 { 79 cin>>n>>m; 80 int a,b,v; 81 for(int i=0;i<m;i++) 82 { 83 cin>>a>>b>>v; 84 edge[a].push_back(Edge(b,v)); 85 edge[b].push_back(Edge(a,v)); 86 } 87 } 88 89 void solve() 90 { 91 spfa(1); 92 } 93 94 void print() 95 { 96 cout<<sec[n]<<endl; 97 } 98 99 int main() 100 { 101 read(); 102 solve(); 103 print(); 104 }
AC Code(2):
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <vector> 5 #include <queue> 6 #define MAX_N 5005 7 #define INF 10000000 8 9 using namespace std; 10 11 struct Edge 12 { 13 int dest; 14 int len; 15 Edge(int _dest,int _len) 16 { 17 dest=_dest; 18 len=_len; 19 } 20 Edge(){} 21 }; 22 23 int n,m; 24 int ans=INF; 25 int dis[MAX_N]; 26 int rev[MAX_N]; 27 bool vis[MAX_N]; 28 vector<Edge> edge[MAX_N]; 29 queue<int> q; 30 31 int get_front() 32 { 33 int now=q.front(); 34 q.pop(); 35 vis[now]=false; 36 return now; 37 } 38 39 void insert(int now) 40 { 41 if(vis[now]) return; 42 q.push(now); 43 vis[now]=true; 44 } 45 46 void spfa(int start,int *dis) 47 { 48 memset(dis,0x3f,sizeof(int)*MAX_N); 49 memset(vis,false,sizeof(vis)); 50 insert(start); 51 dis[start]=0; 52 while(!q.empty()) 53 { 54 int now=get_front(); 55 for(int i=0;i<edge[now].size();i++) 56 { 57 Edge temp=edge[now][i]; 58 if(dis[temp.dest]>dis[now]+temp.len) 59 { 60 dis[temp.dest]=dis[now]+temp.len; 61 insert(temp.dest); 62 } 63 } 64 } 65 } 66 67 void read() 68 { 69 cin>>n>>m; 70 int a,b,v; 71 for(int i=0;i<m;i++) 72 { 73 cin>>a>>b>>v; 74 edge[a].push_back(Edge(b,v)); 75 edge[b].push_back(Edge(a,v)); 76 } 77 } 78 79 void solve() 80 { 81 spfa(1,dis); 82 spfa(n,rev); 83 for(int i=1;i<=n;i++) 84 { 85 for(int j=0;j<edge[i].size();j++) 86 { 87 Edge temp=edge[i][j]; 88 if(dis[i]+temp.len+rev[temp.dest]>dis[n]) 89 { 90 ans=min(ans,dis[i]+temp.len+rev[temp.dest]); 91 } 92 } 93 } 94 } 95 96 void print() 97 { 98 cout<<ans<<endl; 99 } 100 101 int main() 102 { 103 read(); 104 solve(); 105 print(); 106 }
以上是关于BZOJ 1726 [Usaco2006 Nov]Roadblocks第二短路:双向spfa次短路的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ 1726 [Usaco2006 Nov]Roadblocks第二短路:双向spfa次短路
bzoj 1726: [Usaco2006 Nov]Roadblocks第二短路dijskstra
[BZOJ1725][Usaco2006 Nov]Corn Fields牧场的安排