我天原来现在经常卡SPFA......
还好有dalao指点 SPFA + 队列 跑稠密图时会退化成将近 的复杂度
具体原因 百度 "卡SPFA" 然后随便进去就行了
这里采用堆存储 关于距离数组 dis 用小根堆维护 每次取dis最小的点更新 等根里没数了就跑完了
一般图优化效果也比较明显 普通模板快了 50ms 然后稠密图优化效果极其显著
说白了还是 SPFA 就不批注了 存个代码警示一下 模板题戳这里
#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;
const int MAXN = 100010;
const int MAXM = 400010;
struct Edge {
int next,to,v;
} e[MAXM];
int first[MAXN],dis[MAXN],heap[MAXN],tot;
short o[MAXN];
void add(int x,int y,int z)
{
e[++tot].next = first[x];
e[tot].to = y;
e[tot].v = z;
first[x] = tot;
}
void push(int p)
{
heap[++tot] = p;
o[p] = 1;
int now = tot;
while (now > 1 && dis[heap[now]] < dis[heap[now / 2]])
swap(heap[now],heap[now / 2]),now = now / 2;
}
int pop(int p)
{
o[heap[1]] = 0;
int po = heap[1];
heap[1] = heap[tot--];
while (p * 2 <= tot && dis[heap[p]] > dis[heap[p * 2]] ||
(p * 2 + 1 <= tot && dis[heap[p]] > dis[heap[p * 2 + 1]]))
{
int nxt = p * 2;
if (nxt + 1 <= tot && dis[heap[nxt]] > dis[heap[nxt + 1]]) ++nxt;
swap(heap[p],heap[nxt]);
p = nxt;
}
return po;
}
int main()
{
memset(dis,0x7f,sizeof(dis));
int n,m,s,x,y,z;
scanf("%d%d%d",&n,&m,&s); while (m--)
scanf("%d%d%d",&x,&y,&z),add(x,y,z);
tot = 0;
push(s);
dis[s] = 0;
while (tot)
{
int p = pop(1);
for (int a = first[p],b = e[a].to ; a ; a = e[a].next,b = e[a].to)
if (dis[p] + e[a].v < dis[b])
{
dis[b] = dis[p] + e[a].v;
if (!o[b]) push(b);
}
}
for (int a = 1 ; a < n ; ++ a)
printf("%d ",dis[a]);
printf("%d\n",dis[n]);
return 0;
}