最短路
spfa
这个东西实际上是通过暴力来松弛。每次能够松弛就松弛一下。
注意到复杂度 \(O(nm)\)。
const int N=1e5+7,inf=(1<<31)-1;
int n,m,s,dis[N],vis[N];
struct node{int v,w;};
vector <node> q[N];
void spfa(){
queue <int> t;for(int i=1;i<=n;i++)dis[i]=inf;
dis[s]=0,t.push(s);
while(!t.empty()){
int u=t.front();t.pop();vis[u]=0;
for(node tmp:q[u]){
int v=tmp.v,w=tmp.w;
if(dis[v]>dis[u]+w){
dis[v]=dis[u]+w;
if(vis[v])continue;
vis[v]=1;t.push(v);
}
}
}
}
spfa 判断负环的方法是记录最短路经过了多少条边。当最短路经过了 \(n\) 条边的时候就代表出现了一个负环。
注意!!!如果判了负环,那么每次做 spfa 的时候都需要重新清空 vis,因为判断完有负环直接就返回了不会自动清空!!!
dij
每次找最小的可以松弛的边松弛。每条边最多被遍历一次。多了一个堆的复杂度。复杂度 \(m\log n\)。
#define pii pair<int,int>
#define mp make_pair
const int N=1e6+7;
int n,m,s,dis[N],vis[N];
priority_queue<pii,vector<pii>,greater<pii>> t;
vector <pii> q[N];
void dij(int s){ //多测记得手动清空 vis 数组!!!
memset(dis,0x3f3f,sizeof(dis));dis[s]=0;t.push(mp(0,s));
while(!t.empty()){
int u=t.top().second;t.pop();if(vis[u])continue;vis[u]=1;
for(pii tmp:q[u]){
int v=tmp.first,w=tmp.second;
if(dis[v]>dis[u]+w){
dis[v]=dis[u]+w;if(vis[v])continue;
t.push(mp(dis[v],v));
}
}
}
}

浙公网安备 33010602011771号