Evanyou Blog 彩带

洛谷P1491 集合位置 [最短路,SPFA]

  题目传送门

  

题目描述

每次有大的活动,大家都要在一起“聚一聚”,不管是去好乐迪,还是避风塘,或者汤姆熊,大家都要玩的痛快。还记得心语和花儿在跳舞机上的激情与释放,还记得草草的投篮技艺是如此的高超,还记得狗狗的枪法永远是'S'……还有不能忘了,胖子的歌声永远是让我们惊叫的!!

今天是野猫的生日,所以想到这些也正常,只是因为是上学日,没法一起去玩了。但回忆一下那时的甜蜜总是一种幸福嘛。。。

但是每次集合的时候都会出现问题!野猫是公认的“路盲”,野猫自己心里也很清楚,每次都提前出门,但还是经常迟到,这点让大家很是无奈。后来,野猫在每次出门前,都会向花儿咨询一下路径,根据已知的路径中,总算能按时到了。

现在提出这样的一个问题:给出n个点的坐标,其中第一个为野猫的出发位置,最后一个为大家的集合位置,并给出哪些位置点是相连的。野猫从出发点到达集合点,总会挑一条最近的路走,如果野猫没找到最近的路,他就会走第二近的路。请帮野猫求一下这条第二最短路径长度。

输入输出格式

输入格式:

 

第一行是两个整数n(1<=n<=200)和m,表示一共有n个点和m条路,以下n行每行两个数xi,yi,(-500<=xi,yi<=500),代表第i个点的坐标,再往下的m行每行两个整数pj,qj,(1<=pj,qj<=n),表示两个点相通。

 

输出格式:

 

只有一行包含一个数,为第二最短路线的距离(保留两位小数),如果存在多条第一短路径,则答案就是第一最短路径的长度;如果不存在第二最短路径,输出-1。

 

输入输出样例

输入样例#1: 复制
  1. 3 3
  2. 0 0
  3. 1 1
  4. 0 2
  5. 1 2
  6. 1 3
  7. 2 3
输出样例#1: 复制
  1. 2.83

说明

各个测试点1s

 


 

 

  分析:开始在网上看到了一个Dijkstra算法一次性求最短路和次短路,然后决定来拿这题练手,结果...感人肺腑的卡了两个小时,死活有两个点会wa掉。最后没办法就索性打了个暴力spfa+删边。。。然后之前那个还没调对。。。两份代码都放一下吧。

  Code:

(Dijkstra)

 

复制代码
  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int N=407;
  4. #define INF 1e9+7
  5. typedef pair<double,int>P;
  6. int n,m;
  7. double di[N][N],dis[N],dist[N];
  8. struct pos{int x,y;}a[N];
  9. struct node{
  10. int to;double val;
  11. node(int x=0,double y=0):
  12. to(x),val(y){}};
  13. vector<node>g[N];
  14. void dijkstra()
  15. {
  16. priority_queue<P, vector<P>, greater<P> >team;
  17. fill(dis,dis+n+1,INF);
  18. fill(dist,dist+n+1,INF);
  19. dis[1]=0;
  20. team.push(P(0,1));
  21. while(!team.empty()){
  22. P p=team.top();team.pop();
  23. int x=p.second;
  24. double d=p.first;
  25. if(dist[x]<d)continue;
  26. for(int i=0;i<g[x].size();i++){
  27. node e=g[x][i];
  28. double dt=d+e.val;
  29. if(dis[e.to]>dt){
  30. swap(dis[e.to],dt);
  31. team.push(P(dis[e.to],e.to));
  32. }
  33. if(dist[e.to]>dt&&dis[e.to]<dt){
  34. dist[e.to]=dt;
  35. team.push(P(dist[e.to],e.to));
  36. }
  37. }
  38. }
  39. if(dist[n]<dist[0])
  40. printf("%.2lf",dist[n]);
  41. else
  42. printf("-1");
  43. }
  44. double get(int A,int B)
  45. {
  46. double x1=a[A].x*1.0,y1=a[A].y*1.0;
  47. double x2=a[B].x*1.0,y2=a[B].y*1.0;
  48. return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
  49. }
  50. int main()
  51. {
  52. scanf("%d%d",&n,&m);
  53. int x,y;
  54. for(int i=1;i<=n;i++)
  55. scanf("%d%d",&a[i].x,&a[i].y);
  56. for(int i=1;i<n;i++)
  57. for(int j=i+1;j<=n;j++)
  58. di[i][j]=di[j][i]=get(i,j);
  59. for(int i=1;i<=m;i++){
  60. scanf("%d%d",&x,&y);
  61. g[x].push_back(node{y,di[x][y]});
  62. g[y].push_back(node{x,di[y][x]});}
  63. dijkstra();
  64. return 0;
  65. }
复制代码

 

 

(SPFA+删边)

 

复制代码
  1. #include<bits/stdc++.h>
  2. #define Fi(a,b,c) for(int a=b;a<=c;a++)
  3. #define Fx(a,b,c) for(int a=b;a>=c;a--)
  4. using namespace std;
  5. const int N=2007;
  6. int n,m,head[N],size,pre[N];
  7. double d[N][N],dis[N],ans;
  8. bool vis[N];
  9. struct Poi{int x,y;}a[N];
  10. struct Node{
  11. int to,next;double val;
  12. }edge[N<<5];
  13. inline int read()
  14. {
  15. char ch=getchar();int num=0;bool flag=false;
  16. while(ch<'0'||ch>'9'){if(ch=='-')flag=true;ch=getchar();}
  17. while(ch>='0'&&ch<='9'){num=num*10+ch-'0';ch=getchar();}
  18. return flag?-num:num;
  19. }
  20. inline void add(int x,int y,double z)
  21. {
  22. edge[++size].to=y;
  23. edge[size].val=z;
  24. edge[size].next=head[x];
  25. head[x]=size;
  26. }
  27. inline double get(int x,int y)
  28. {
  29. double x1=a[x].x*1.0,y1=a[x].y*1.0;
  30. double x2=a[y].x*1.0,y2=a[y].y*1.0;
  31. return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
  32. }
  33. void spfa()
  34. {
  35. memset(vis,false,sizeof(vis));
  36. Fi(i,1,n)dis[i]=0x3f3f3f3f;
  37. queue<int>team;team.push(1);
  38. dis[1]=0;vis[1]=true;
  39. while(!team.empty()){
  40. int x=team.front();team.pop();vis[x]=false;
  41. for(int i=head[x];i!=-1;i=edge[i].next){
  42. int y=edge[i].to;
  43. if(dis[y]>dis[x]+edge[i].val){
  44. dis[y]=dis[x]+edge[i].val;pre[y]=x;
  45. if(!vis[y]){team.push(y);vis[y]=true;}}}}
  46. }
  47. inline double SPFA(int u,int v)
  48. {
  49. memset(vis,false,sizeof(vis));
  50. Fi(i,1,n)dis[i]=0x3f3f3f3f;
  51. queue<int>team;team.push(1);
  52. dis[1]=0;vis[1]=true;
  53. while(!team.empty()){
  54. int x=team.front();team.pop();vis[x]=false;
  55. for(int i=head[x];i!=-1;i=edge[i].next){
  56. int y=edge[i].to;if((x==u&&y==v)||(x==v&&y==u))continue;
  57. if(dis[y]>dis[x]+edge[i].val){
  58. dis[y]=dis[x]+edge[i].val;
  59. if(!vis[y]){team.push(y);vis[y]=true;}}}}
  60. return dis[n];
  61. }
  62. int main()
  63. {
  64. n=read();m=read();
  65. memset(head,-1,sizeof(head));
  66. Fi(i,1,n)a[i].x=read(),a[i].y=read();
  67. Fi(i,1,n-1) Fi(j,i+1,n)
  68. d[i][j]=d[j][i]=get(i,j);
  69. Fi(i,1,m){int x=read();int y=read();
  70. add(x,y,d[x][y]);add(y,x,d[y][x]);}
  71. spfa();ans=0x3f3f3f3f;int f=n;
  72. while(555){
  73. double ka=SPFA(pre[f],f);
  74. if(ans>ka)ans=ka;f=pre[f];
  75. if(f==1)break;}
  76. if(ans>999999)printf("-1");
  77. else printf("%.2lf",ans);
  78. return 0;
  79. }
复制代码

 

posted @   HolseLee  阅读(437)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示