最短路

 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被卡后都不敢用了 

 

posted @ 2021-11-19 19:44  yfmd  阅读(32)  评论(0编辑  收藏  举报