码迷,mamicode.com
首页 > 数据库 > 详细

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

时间:2017-10-06 16:53:23      阅读:157      评论:0      收藏:0      [点我收藏+]

标签:com   name   lin   print   des   i++   ring   out   new   

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

标签:com   name   lin   print   des   i++   ring   out   new   

原文地址:http://www.cnblogs.com/Leohh/p/7631724.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!