bzoj4773: 负环
题解:
网上还有一种spfa+深度限制的算法
https://www.cnblogs.com/BearChild/p/6624302.html
是不加队列优化的spfa,我觉得复杂度上限是bellman-ford nm的,另外从每个点跑加上二分答案所以是n^2mlogn的
但实测的确是挺快的,可能是深度限制的原因
这题可以用倍增floyd
比较慢的就是二分+倍增floyd是n^3log^2n的
可以直接用找lca的思想,做到n^3logn
不太懂floyd的理论
两个矩阵算起来的时候要用新矩阵去更新的
c[i][j]=min(c[i][j],a[i][k]+b[k][j])这样做
然后卡了一下常(指针)
不过在bz上效果好像不是很明显
自己测试还是很明显得
不过windos下数组极慢,要用5.5s
linux下只用了2s,指针的win和linux下几乎相同都是1s
代码:
#include <bits/stdc++.h> using namespace std; #define rint register int #define IL inline #define rep(i,h,t) for (rint i=h;i<=t;i++) #define dep(i,t,h) for (rint i=t;i>=h;i--) const int INF=1e9; const int N=400; char ss[1<<24],*A=ss,*B=ss; IL char gc() { return (A==B&&(B=(A=ss)+fread(ss,1,1<<24,stdin),A==B)?EOF:*A++); } template<class T>void read(T &x) { rint f=1,c; while (c=gc(),c<48||c>57) if (c=='-') f=-1; x=c^48; while (c=gc(),47<c&&c<58) x=(x<<3)+(x<<1)+(c^48); x*=f; } int f[13][N][N],t[N][N],t1[N][N],n,m; int main() { freopen("1.in","r",stdin); freopen("1.out","w",stdout); read(n); read(m); rep(k,0,8) rep(i,1,n) rep(j,1,n) if (i!=j) f[k][i][j]=INF; rep(i,1,m) { int x,y,z; read(x); read(y); read(z); if (f[0][x][y]>z) f[0][x][y]=z; } rep(i,1,8) { rep(i1,1,n) rep(i2,1,n) { rint tmp=f[i-1][i2][i1]; rint *p1=f[i-1][i1]; rep(i3,1,n) { rint *p3=f[i][i2]; rint p4=p3[i3]; rint p2=tmp+p1[i3]; if (p4>p2) p3[i3]=p2; } } } rep(i,1,n) rep(j,1,n) t[i][j]=f[0][i][j]; int ans=1; dep(i,8,0) { rep(i1,1,n) rep(i2,1,n) t1[i1][i2]=INF; rep(i1,1,n) { rint (*g)=f[i][i1]; rep(i2,1,n) { rint tmp=t[i2][i1]; rint *p3=t1[i2]; rep(i3,1,n) { rint p1=p3[i3]; rint p2=tmp+g[i3]; if (p1>p2) p3[i3]=p2; } } } bool tt=0; rep(j,1,n) if (t1[j][j]<0) tt=1; if (!tt) { ans+=1<<i; memcpy(t,t1,sizeof(t1)); } } if (ans+1==513) cout<<0<<endl; else cout<<ans+1<<endl; return 0; }