Luogu P1491 集合位置 (spfa--次短路)

本文介绍了一种求解次短路径问题的方法,通过SPFA算法结合边删除策略,实现对次短路径的有效求解。适用于点数不多于200的情况。

题目描述

每次有大的活动,大家都要在一起“聚一聚”,不管是去好乐迪,还是避风塘,或者汤姆熊,大家都要玩的痛快。还记得心语和花儿在跳舞机上的激情与释放,还记得草草的投篮技艺是如此的高超,还记得狗狗的枪法永远是'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: 复制
3 3
0 0
1 1
0 2
1 2
1 3
2 3
输出样例#1: 复制
2.83

说明

各个测试点1s


大概就是求次短路
好像可以用A*来求k短路,不过我不会。。。
那就换一种思路
既然不是最短路,那么它的路径就一定不能和最短路完全重合
也就是说,至少会有一条边与最短路不同
但是我们不知道哪条/哪些边会与最短路不同
那么我们在第一次spfa时记录下来路径(前驱结点)
然后我们就枚举边,将最短路里的每条边都删去一次之后再跑一边spfa求最短路
这个题显然两个点之间只会有一条边相连,所以这个题中枚举边等价于枚举最短路上的相邻两点
这样求出次短路
而且最多也就只有200个点,所以这种方法是行得通的!
代码(跑的比较慢,空间占的也比较多,有空可能会优化一下。。。):

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>
#define For(i,l,r) for(int i=l;i<=r;++i)
using namespace std;
int read()
{
    char c;
    bool t=0;
    int a=0;
    while((c=getchar())==' '||c=='\n'||c=='\r');
    if(c=='-')
    {
        t=1;
        c=getchar();
    }
    while(isdigit(c))
    {
        a*=10;
        a+=(c-'0');
        c=getchar();
    }
    return a*(t?-1:1);
}
struct line{
    int to,next;
    double v;
}edge[80010];
struct poi{
    int x,y;
}node[201];
int last[201],pre[201],n,m;
double dis[201];
bool vis[201];
double dist(int x,int y)
{
    return sqrt((node[x].x-node[y].x)*(node[x].x-node[y].x)+(node[x].y-node[y].y)*(node[x].y-node[y].y));
}
void add(int from,int to,int i)
{
    edge[i].next=last[from];
    last[from]=i;
    edge[i].to=to;
    edge[i].v=dist(from,to);
}
void spfa()
{
    int tx;
    memset(dis,127,sizeof dis);
    queue<int> q;
    q.push(1);dis[1]=0;vis[1]=1;
    while(!q.empty())
    {
        tx=last[q.front()];
        while(tx)
        {
            if(dis[q.front()]+edge[tx].v<dis[edge[tx].to])
            {
                dis[edge[tx].to]=dis[q.front()]+edge[tx].v;
                pre[edge[tx].to]=q.front();
                if(!vis[edge[tx].to])
                {
                    q.push(edge[tx].to);
                    vis[edge[tx].to]=1;
                }
            }
            tx=edge[tx].next;
        }
        vis[q.front()]=0;
        q.pop();
    }
    return;
}
void spfa2(int x,int y)
{
    int tx;
    memset(dis,127,sizeof dis);
    queue<int> q;
    q.push(1);dis[1]=0;vis[1]=1;
    while(!q.empty())
    {
        tx=last[q.front()];
        while(tx)
        {
            if((q.front()==x&&edge[tx].to==y)||(q.front()==y&&edge[tx].to==x))
            {
                tx=edge[tx].next;
                continue;
            }
            if(dis[q.front()]+edge[tx].v<dis[edge[tx].to])
            {
                dis[edge[tx].to]=dis[q.front()]+edge[tx].v;
                if(!vis[edge[tx].to])
                {
                    q.push(edge[tx].to);
                    vis[edge[tx].to]=1;
                }
            }
            tx=edge[tx].next;
        }
        vis[q.front()]=0;
        q.pop();
    }
    return;
}
int main()
{
    int tx,ty,now;
    double ans=0,tmp;
    n=read();m=read();now=n;
    m+=m;
    For(i,1,n)
    {
        node[i].x=read();
        node[i].y=read();
    }
    For(i,1,m)
    {
        tx=read();
        ty=read();
        add(tx,ty,i++);
        add(ty,tx,i);
    }
    spfa();
    while(now!=1)
    {
        spfa2(now,pre[now]);
        if(dis[n]<ans||!ans)
         ans=dis[n];
        now=pre[now];
    }
    printf("%.2f",ans);
    return 0;
}
内容概要:本文系统介绍了算术优化算法(AOA)的基本原理、核心思想及Python实现方法,并通过图像分割的实际案例展示了其应用价值。AOA是一种基于种群的元启发式算法,其核心思想来源于四则运算,利用乘除运算进行全局勘探,加减运算进行局部开发,通过数学优化器加速函数(MOA)和数学优化概率(MOP)动态控制搜索过程,在全局探索与局部开发之间实现平衡。文章详细解析了算法的初始化、勘探与开发阶段的更新策略,并提供了完整的Python代码实现,结合Rastrigin函数进行测试验证。进一步地,以Flask框架搭建前后端分离系统,将AOA应用于图像分割任务,展示了其在实际工程中的可行性与高效性。最后,通过收敛速度、寻优精度等指标评估算法性能,并提出自适应参数调整、模型优化和并行计算等改进策略。; 适合人群:具备一定Python编程基础和优化算法基础知识的高校学生、科研人员及工程技术人员,尤其适合从事人工智能、图像处理、智能优化等领域的从业者;; 使用场景及目标:①理解元启发式算法的设计思想与实现机制;②掌握AOA在函数优化、图像分割等实际问题中的建模与求解方法;③学习如何将优化算法集成到Web系统中实现工程化应用;④为算法性能评估与改进提供实践参考; 阅读建议:建议读者结合代码逐行调试,深入理解算法流程中MOA与MOP的作用机制,尝试在不同测试函数上运行算法以观察性能差异,并可进一步扩展图像分割模块,引入更复杂的预处理后处理技术以提升分割效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值