最短路

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));
			}
		}
	}
}
posted @ 2025-08-19 09:43  all_for_god  阅读(16)  评论(0)    收藏  举报