poj 2253 求可达路上的最大边,dijkstra,spfa

本文详细介绍了两种经典的最短路径算法:Dijkstra算法和SPFA算法。通过具体实例讲解了如何利用这两种算法寻找两点间最大权重边的路径,并提供了完整的C++代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/*
http://acm.pku.edu.cn/JudgeOnline/problem?id=2253
求可达路上的权值最大的边
在dijkstra中,d[i]表示源点s到i的最短路径,这里根据题目要求修改d[i]为“未访问”节点和“已访问”节点,两个点集之间的最短路
则松弛条件为:d[i]=min(d[i],path[mark][i]);
在算浮点数时,可将所有的路径都用int来表示,最后才开方。
spfa是bellman_ford的优化,省去很多冗余的操作
期望的时间复杂度O(ke), 其中k为所有顶点进队的平均次数,可以证明k一般小于等于2。
实现方法:建立一个队列,初始时队列里只有起始点
建立一个path记录起始点到所有点的最短路径(该表格的初始值要赋为极大值,该点到他本身的路径赋为0)。
然后执行松弛操作,用队列里有的点去刷新起始点到所有点的最短路,如果刷新成功且被刷新点不在队列中则把该点加入到队列最后。
重复执行直到队列为空
判断有无负环:如果某个点进入队列的次数超过N次则存在负环(SPFA无法处理带负环的图)
*/
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<vector>
#include<set>
#include<queue>
#include<map>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<functional>
using namespace std;
const int INF=(1<<31)-1;
const double INF_DOUBLE=1e8;
const double EPS=1e-8;
const int N=210; 
int n;
int path[N][N];
struct point
{
  int x,y;     
}p[N];

int calDis(int i,int j)
{
   return (p[i].x-p[j].x)*(p[i].x-p[j].x)+(p[i].y-p[j].y)*(p[i].y-p[j].y);      
}

double dijkstra(int s,int t)
{
       int d[N];
       bool v[N];
       memset(v,false,sizeof(v));
       for(int i=1;i<=n;i++)d[i]=path[s][i];
       v[s]=true;
       int ans=-1;
       while(true)
       {
         int Min=INF;
         int mark=-1;
         for(int i=1;i<=n;i++)
          if(!v[i]&&d[i]<Min){Min=d[i];mark=i;}
         if(mark==-1)return ans;
         v[mark]=true;
         ans=max(ans,Min);
         if(mark==t)return ans; 
         for(int i=1;i<=n;i++)
          if(!v[i]&&d[i]>path[mark][i])
           d[i]=path[mark][i];                   
       }      
}
double spfa(int s,int t)
{
    int d[N];
    bool in_q[N];
    for(int i=1;i<=n;i++)d[i]=INF;
    memset(in_q,false,sizeof(in_q));
    d[s]=0;
    queue<int>q;
    q.push(s);    
    in_q[s]=true;
    while(!q.empty())
    {
       int temp=q.front(); 
       q.pop();
       in_q[temp]=false;
       for(int i=1;i<=n;i++)
        if(d[i]>max(d[temp],path[temp][i]))
        {
          d[i]=max(d[temp],path[temp][i]);
          if(!in_q[i])
          {
             q.push(i);
             in_q[i]=true;
          }
        }                
    }
    return d[t];
}
int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int T=1;
    while(cin>>n,n)
    {
       int a,b;
       for(int i=1;i<=n;i++){scanf("%d %d",&p[i].x,&p[i].y);}
       for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
         path[i][j]=calDis(i,j);
       printf("Scenario #%d/nFrog Distance = %.3lf/n/n",T++,sqrt(dijkstra(1,2)));                       
    }
    //system("pause");
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值