最短路
dijkstra
O ( ( m + n ) l o g n ) O((m+n)log_n) O((m+n)logn)
基于贪心思想,不能处理负边权(每个点第一次出为最短路,但负边权若离源点较远,还没更新到就已确定了答案)
inline void dijkstra(){
memset(dis,0x3f,sizeof(dis));
memset(vis,0,sizeof(vis));
dis[1]=0;
priority_queue<pair<int,int>>q;
q.push(make_pair(0,1));
while(!q.empty()){
int x-q.top();q.pop();
if(vis[x])continue;
vis[x]=1;
for(int i=first[x],v;i;i=e[i].nxt){
v=e[i].v;
if(dis[v]>dis[x]+e[i].w){
dis[v]=dis[x]+e[i].w;
q.push(make_pair(-dis[v],v));
}
}
}
}
SPFA
复杂度玄学,最坏 O ( n m ) O(nm) O(nm)
判负环: c n t [ x ] cnt[x] cnt[x]表示从1到 n n n的最短路包含的边数, c n t [ 1 ] = 0 cnt[1]=0 cnt[1]=0,若发现 c n t [ v ] > = n cnt[v]>=n cnt[v]>=n则有负环(也可以判一个点入队大于等于 n n n次,但复杂度低些)
别用双端队列优化,卡的更凶,且无法判负环(入队 n n n次也不一定是被更新了 n n n次), d f s dfs dfs版也会被卡
queue<int>q;
inline bool spfa(){
memset(dis,0x3f,sizeof(dis));
memset(vis,0,sizeof(vis));
q.push(1);
vis[1]=1;dis[1]=0;
while(!q.empty()){
int x=q.front();q.pop();
vis[x]=0;
for(int i=first[x],v;i;i=e[i].nxt){
v=e[i].v;
if(dis[v]>dis[x]+e[i].w){
dis[v]=dis[x]+e[i].w;
cou[v]=cou[x]+1;//!!
if(cou[v]>=n)return 1;
if(!vis[v]){
vis[v]=1;
q.push(v);
}
}
}
}
return 0;
}
floyd
任意两点之间最短路, O ( n 3 ) O(n^3) O(n3)
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
求传递闭包
关系具有传递性,且传递性推导出尽量多的元素之间的关系,如判有向图,一个点是否能到达另一个点
普通版
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
b[i][j]|=b[i][k]&b[k][j];
b i t s e t bitset bitset版
bitset<N>b[N];
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(f[j].test(i))f[j]|=f[i];//用f[i]更新f[j]
最小环:
在 f l o y d floyd floyd中再开一个更新答案
vector<int>path;
inline void get_path(int x,int y){
if(pox[x][y]