1 //弗洛伊德 floyd
2 void floyd()// n3
3 {
4 //想象为在拉面条,不断进行松弛操作
5 for(ll k=1;k<=n;++k)//k必须放在最外层
6 for(ll i=1;i<=n;++i)//枚举两端点
7 for(ll j=1;j<=n;++j)
8 g[i][j]=min(g[i][j],g[i][k]+g[k][j]);
9 }
10 //迪杰斯特拉 dijkstra
11 //本质为贪心,即每次取距离最短的点,不断进行松弛操作
12 //时间复杂度:未加堆优化时是n^2,加了堆优化后是nlogn
13 //稳定性很强,但是仅适用于正边权,有负边权就game over了
14 ll dis[N],head[M];
15 bool vis[N];
16 struct node
17 {
18 ll len,poi;
19 friend bool operator < (node a,node b)
20 {
21 return a.len>b.len;
22 }
23 }
24 struct edge
25 {
26 ll nex,to,lenth;
27 }e[M];
28 void dijkstra()//堆优化
29 {
30 dis[start]=0;
31 q.push((node){0,start});
32 while(!q.empty())
33 {
34 node u=q.top();q.pop();
35 l x=u.poi,d=u.dis;
36 if(vis[x])continue;
37 vis[x]=1;
38 for(ll i=head[x];i;i=e[i].nex)
39 {
40 ll v=e[i].to,l=e[i].lenth;
41 if(v==u)continue;
42 if(dis[v]>dis[u]+lenth)
43 {
44 dis[v]=dis[u]+lenth;
45 if(vis[v])continue;
46 q.push((node){dis[v],v});
47 }
48 }
49 }
50 }
51 // spfa
52 // 动态逼近法,也是不断松弛,能够判断负环,即一个点入队次数超过n次
53 // 可以用于负边权
54 queue<ll>q;
55 void spfa()//该代码没判断负环哦
56 {
57 q.push(start);dis[start]=0;vis[start]=1;
58 while(!q.empty())
59 {
60 ll u=q.front();q.pop();vis[u]=0;
61 for(ll i=head[u];i;i=e[i].nex)
62 {
63 ll v=e[i].to,l=e[i].len;
64 if(dis[v]>dis[u]+l)
65 {
66 dis[v]=dis[u]+l;
67 if(vis[v]==0)
68 {
69 q.push(v);vis[v]=1;
70 }
71 }
72 }
73 }
74 }
75 // dijkstra和spfa其实是很像的
76 // 稠密图:dijstra+堆优化 更好
77 // 稀疏图:spfa 更好
78 // 建议用dijkstra,spfa自从在NOI2018被卡后都不敢用了