1. 程式人生 > >BZOJ 1726 [Usaco2006 Nov]Roadblocks第二短路:雙向spfa【次短路】

BZOJ 1726 [Usaco2006 Nov]Roadblocks第二短路:雙向spfa【次短路】

for star pan spf n) com 情況 三種 雙向

題目鏈接: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【次短路】