最短路的一些板子

  起因是一场训练赛,这道题(LA 5854 Long Distance Taxi)我和Thor拿出了正解(之一),但非常令人发指地送出了不计其数的TLE。

  题干不说了,我们的做法是前向星建图,然后每个LPG(起点终点也算LPG)跑一遍SPFA,然后所有LPG重新前向星建图,再跑一遍SPFA。复杂度大概是O(k1*n+k2*m^2),按理说不会超时啊……

  然后我们发现sd0061的做法前面和我们一样,后面建邻接矩阵,跑一遍Floyd,理论复杂度是O(k*n+m^3);令人发指的是竟然比我们的程序快一倍……

  于是我和Thor开始了大规模的研究。具体过程按下不表,其中重要的一点是,我们发现两次建图中第一次是稀疏图,第二次是稠密图。最终结论是:

  对于稀疏图,优先使用前向星或邻接表+SPFA(为保证速度避免使用vector);对于稠密图,优先使用邻接矩阵+Dijkstra。

  算法上,设某图点数为V,边数为E。邻接矩阵+裸Dijkstra复杂度是O(V^2),邻接表+Dijkstra+priority_queue的复杂度是O((V+E)logV),速度上是最稳定的;Barty的板子是Dijkstra+heap,但heap用set去实现,复杂度相同但实测速度上要慢上一些。前向星+SPFA+SLF+LLL的理论复杂度依旧是最快的O(k*E),但是常数k很不稳定,有退化成O(V*E)的可能;其中两个优化同时使用效果会好一些。

  所以如果图是稠密图,那么用SPFA就是作死……但是如果图中有负权边,又必须放弃Dijkstra投奔SPFA的怀抱……如果是带负权边的稠密图,提刀砍向出题人吧……

  此外从Bellman-Ford改过来的SPFA还可判负环。

  目前Damocles已有的最短路板子速度上已经比较快,基本不会再改了。贴出来供参考。

  建图:

const int MAXN=100005;
const int MAXM=200005;
struct graph
{
    int head[MAXN];
    int to[MAXM];
    int next[MAXM];
    int len[MAXM];
    int tot;
    void init()
    {
        tot=0;
        memset(head,0xff,sizeof(head));
    }
    void add(int x,int y,int z)
    {
        to[tot]=y;
        len[tot]=z;
        next[tot]=head[x];
        head[x]=tot++;
    }
} g;

  Dijkstra+priority_queue+邻接表,邻接矩阵的在此基础上随便改改就成:

int dist[MAXM];
void dijkstra(int src)
{
    memset(dist,0x3f,sizeof(dist));
    dist[src]=0;
    priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > > pq;
    pq.push(make_pair(dist[src],src));
    while(!pq.empty())
    {
        int x=pq.top().second;
        int d=pq.top().first;
        pq.pop();
        if(d!=dist[x])
            continue;
        for(int i=g.head[x]; ~i; i=g.next[i])
        {
            int y=g.to[i];
            if(d+g.len[i]<dist[y])
            {
                dist[y]=d+g.len[i];
                pq.push(make_pair(dist[y],y));
            }
        }
    }
}

  SPFA+SLF+LLL+邻接表,这个就别改邻接矩阵了,太慢:

int dist[MAXM];
bool inque[MAXM];
void spfa(int src)
{
    memset(dist,0x3f,sizeof(dist));
    memset(inque,false,sizeof(inque));
    dist[src]=0;
    deque<int> q;
    q.push_back(src);
    inque[src]=true;
    long long sum=0;
    while(!q.empty())
    {
        int x=q.front();
        q.pop_front();
        if(!q.empty()&&(long long)dist[x]*q.size()>sum)
        {
            q.push_back(x);
            continue;
        }
        sum-=dist[x];
        inque[x]=false;
        for(int i=g.head[x]; ~i; i=g.next[i])
        {
            int y=g.to[i];
            int d=dist[x]+g.len[i];
            if(d<dist[y])
            {
                if(inque[y])
                    sum+=d-dist[y];
                dist[y]=d;
                if(!inque[y])
                {
                    if(!q.empty()&&dist[q.front()]>dist[y])
                        q.push_front(y);
                    else
                        q.push_back(y);
                    sum+=dist[y];
                    inque[y]=true;
                }
            }
        }
    }
}

  基本上比赛能用上的就这两份板子了,根据情况改图或增减优化即可。通常来讲SPFA不加SLF和LLL优化也够用了。

由于没有提供具体参考引用,以下是关于野火板子烧录的通用信息。 ### 烧录方法 #### ST - Link 烧录 ST - Link 是一种常用的烧录工具,支持 STM32 系列芯片的烧录。 1. 硬件连接:将 ST - Link 调试器的 SWD 接口与野火板子上对应的 SWD 接口连接,一般包括 SWCLK(时钟线)、SWDIO(数据线)、GND(地线)和 VCC(电源线)。 2. 软件配置:安装 ST - Link 驱动,打开烧录软件如 STM32CubeProgrammer 或 Keil MDK。在软件中选择正确的芯片型号,配置烧录参数,如波特率、烧录模式等。 3. 烧录操作:选择要烧录的固件文件(通常为.hex 或.bin 格式),点击烧录按钮,软件会自动将固件写入芯片。 ```python # 示例代码仅为示意,非实际运行代码 # 假设使用 Python 和 PySTLink 库进行烧录 import pystlink # 初始化 ST - Link stlink = pystlink.STLink() # 连接到目标芯片 stlink.connect() # 打开固件文件 with open('firmware.hex', 'rb') as f: firmware = f.read() # 烧录固件 stlink.flash(firmware) # 断开连接 stlink.disconnect() ``` #### J - Link 烧录 J - Link 也是一款功能强大的调试和烧录工具。 1. 硬件连接:将 J - Link 调试器的 JTAG 或 SWD 接口与野火板子连接,确保引脚对应正确。 2. 软件配置:安装 J - Link 驱动和相关烧录软件,如 Segger J - Flash。在软件中设置芯片型号和烧录配置。 3. 烧录操作:导入固件文件,点击烧录选项,完成烧录过程。 #### USB 串口烧录 部分野火板子支持通过 USB 串口进行烧录。 1. 硬件连接:使用 USB 线将野火板子与电脑连接,确保板子处于正确的烧录模式。 2. 软件配置:安装串口驱动,使用串口烧录工具如 FlyMcu。设置串口参数和固件文件。 3. 烧录操作:点击开始烧录按钮,烧录工具会通过串口将固件传输到板子。 ### 注意事项 1. 硬件连接:确保烧录工具与野火板子的连接正确,引脚无松动或短路。在连接前,检查电源和接地情况,避免损坏芯片。 2. 芯片型号:在烧录软件中选择正确的芯片型号,否则可能导致烧录失败或芯片损坏。 3. 固件文件:确保使用的固件文件与目标芯片和板子兼容,文件格式正确。 4. 烧录模式:有些板子需要进入特定的烧录模式才能进行烧录,如通过跳线或按键设置。在烧录前,确认板子处于正确的烧录模式。 5. 电源供应:烧录过程中,保证板子有稳定的电源供应,避免因电源波动导致烧录中断。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值