专栏文章

SPFA又被我救活了

个人记录参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@minp4dr3
此快照首次捕获于
2025/12/02 06:03
3 个月前
此快照最后确认于
2025/12/02 06:03
3 个月前
查看原文
CPP
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define getchar_fread() (p1==p2&&(p2=(p1=buf)+fread(buf,1,MAXN,stdin),p1==p2)?EOF:*p1++)
#define flush() (fwrite(buffer,1,q1+1,stdout),q1=-1)
const int MAXN=1<<15,N=1e6+8,M=5e6+8;
const ll C=0x3f3f3f3f3f3f3f3f;
char *p1,*p2,buf[MAXN],buffer[MAXN];
int q1=-1,q2=MAXN-1,j=0;
inline void putchar_fwrite(char x){if (q1==q2) flush();buffer[++q1]=x;}
template<typename T>
inline void read(T &x){x=0;
    T c=getchar_fread(),f=0;
    while(!isdigit(c)){if(c=='-') f=1;c=(T)getchar_fread();}
    while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=(T)getchar_fread();
    if (f) x=~x+1;
}
template<typename T>
inline void write(T x){
	if (x<0) putchar_fwrite('-'),x=~x+1;
	T print[65];
	while (x) print[++j]=x%10,x/=10;
	if (j==0) print[++j]=0;
	while (j) putchar_fwrite(print[j--]^48);
}
struct G{int x,t,qq;ll u;} a[M];
int n,m,h[N],cnt=0;
struct Tar{int dfn,low;} g[N];
ll ans[N],z;
int p[N],c[N],l,stk[N],top=0,w[N],k[N],t[N],u,v;
void tarjan(int x){
    g[x].dfn=g[x].low=++l;
    stk[++top]=x;k[x]=w[x]=1;
    for (int i=h[x];i;i=a[i].t){v=a[i].x;
        if (a[i].qq==0) continue;
        if (g[v].dfn&&k[v]) --p[v];
        if (!g[v].dfn) tarjan(v);
        if (w[v]) g[x].low=min(g[x].low,g[v].low);
    }if (g[x].dfn==g[x].low){
        int y=0;
        while (x!=y) y=stk[top--],w[y]=0;
    }k[x]=0;
}
struct pri{
	int x;ll u;
	inline bool operator<(const pri&other)const{return u>other.u;}
};
struct spf{
	int x,f,t,dep;
	inline bool operator<(const spf&other)const{
		if (t!=other.t) return t<other.t;
		return dep>other.dep;
	}
};
template <typename T>
class Priority_Queue:public priority_queue<T>{
	public:void reserve(size_t n){this->c.reserve(n);}
};
inline void init(int s){
    memset(g,0,sizeof(g));
	memset(p,0,sizeof(p));
	memset(w,0,sizeof(w));
    memset(t,0,sizeof(t));
    memset(c,0,sizeof(c));
    memset(ans,C,sizeof(ans));
    for (int i=1;i<=cnt;++i) a[i].qq=0;
	Priority_Queue <pri> q;
	q.reserve(m);ans[s]=0;
	w[s]=s;q.push({s,0});l=0;
	while (!q.empty()){
		u=q.top().x;q.pop();
		if (c[u]) continue;
		++l;if (l==n) break;
		for (int i=h[u];i;i=a[i].t){v=a[i].x;
		    if (v==w[u]) continue;
			++p[v];a[i].qq=1;
			if (ans[v]>ans[u]+a[i].u){
    			ans[v]=ans[u]+a[i].u,w[v]=u,c[v]=c[u]+1;
    			if (c[v]==0) q.push({v,a[i].u});
            }
		}
	}
	memset(w,0,sizeof(w));
	l=0,tarjan(s);
	memset(w,0,sizeof(w));
	w[s]=t[s]=1;
}
inline bool spfa(int s){
    Priority_Queue <spf> sta;
    init(s);sta.reserve(n);
    sta.push({s,1,1,1});
    while (!sta.empty()){
        spf tp=sta.top();u=tp.x;
        sta.pop();w[u]=0;
		if (c[u]>n) return 0;
        for (int i=h[u];i;i=a[i].t){l=0,v=a[i].x;
            if (ans[v]>ans[u]+a[i].u)
                c[v]=c[u]+1,ans[v]=ans[u]+a[i].u,l=1;
            if (!w[v]&&(p[v]==1&&tp.f||l&&p[v]==0)) w[v]=1,sta.push({v,p[v],++t[v],c[v]});
            if (tp.f&&p[a[i].x]>0) --p[a[i].x];
        }
    }return 1;
}
signed main(){
    int s;
	read(n),read(m),read(s);
	for (int i=1,x,y,z;i<=m;++i){
	    read(x),read(y),read(z);
	    if (x==y) continue;
	    a[++cnt]={y,h[x],0,z};h[x]=cnt;
	}
	if (!spfa(s)) return cout <<"No answer.",0;
	for (int i=1;i<=n;++i) write(ans[i]),putchar_fwrite(' ');
	flush();
	return 0;
}
//拓扑排序、最小生成树思想与加速路径传播优化spfa
初测时间复杂度为O((n+m)logn)O((n+m)logn),可以判负权图

评论

0 条评论,欢迎与作者交流。

正在加载评论...