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;
}

 

posted @ 2018-08-16 23:33  尹吴潇  阅读(124)  评论(0编辑  收藏