2 条题解

  • 0
    @ 2026-6-16 21:41:04

    // 负环 SPFA 算法 O(kM~NM)
    #include<bits/stdc++.h>
    using namespace std;
    
    const int N=510,M=5210;
    int idx,h[N],to[M],ww[M],ne[M];
    void add(int a,int b,int c){
      to[++idx]=b,ww[idx]=c,ne[idx]=h[a],h[a]=idx;
    }
    int n,m1,m2;
    int d[N],cnt[N];
    bool vis[N];
    
    bool spfa(){
      memset(d,0,sizeof d);
      memset(cnt,0,sizeof cnt);
      memset(vis,0,sizeof vis);
      queue<int> q;
      for(int i=1; i<=n; i++) q.push(i),vis[i]=true;
      while(!q.empty()){
        int u=q.front(); q.pop(); vis[u]=false;
        for(int i=h[u]; i; i=ne[i]){
          int v=to[i];
          if(d[v]>d[u]+ww[i]){
            d[v]=d[u]+ww[i];
            cnt[v]=cnt[u]+1; //记录走过的边数
            if(cnt[v]==n) return true; //有负环
            if(!vis[v]) q.push(v), vis[v]=true;
          }
        }
      }
      return false; //无负环
    }
    int main(){
      int T; scanf("%d",&T);
      for(int a,b,c;T--;){
        scanf("%d%d%d",&n,&m1,&m2);
        idx=0; memset(h,0,sizeof h);
        for(int i=0; i<m1; i++){
          scanf("%d%d%d",&a,&b,&c);
          add(a,b,c),add(b,a,c);
        }
        for(int i=0; i<m2; i++){
          scanf("%d%d%d",&a,&b,&c);
          add(a,b,-c); //有向边
        }
        
        if(spfa()) puts("YES");
        else puts("NO");
      }
    }
    
    • 0
      @ 2025-10-8 17:00:47

      D03 最短路 Bellman-Ford 算法 SPFA 算法

      /*
      多一个数组dd,dd[x]表示当d[x]时从出发点1到点x经过的点数
      如果dd[x]>n时,说明出现了环,而且环的所有边的权值和为负数。 
      */
      #include<bits/stdc++.h>
      using namespace std;
      typedef pair<int,int> PII;
      const int N=5010;
      vector<PII>G[N];
      int n,d[N],dd[N];bool v[N];
      bool spfa()
      {
          memset(d,0x3f,sizeof(d));
          memset(dd,0,sizeof(dd));
          memset(v,0,sizeof(v));
          queue<int>q;
      	for(int i=1;i<=n;i++) dd[i]=1,v[i]=1,q.push(i);
          while(!q.empty())
          {
              int x=q.front();q.pop();
              v[x]=0;
              for(auto i:G[x])
              {
                  int y=i.first,w=i.second;
                  if(d[y]>d[x]+w)
                  {
                      d[y]=d[x]+w;
                      dd[y]=dd[x]+1;if(dd[y]>n)return true;//怎么可能经过大于n个点,负环 
                      if(!v[y])q.push(y),v[y]=1;
                  }
              }
          }
          return false;
      }
      int main()
      {
          int T;scanf("%d",&T);
          while(T--)
          { 
              int m1,m2;scanf("%d%d%d",&n,&m1,&m2);
              memset(G,0,sizeof(G));
              for(int i=1,x,y,w;i<=m1;i++)scanf("%d%d%d",&x,&y,&w),G[x].push_back({y,w}),G[y].push_back({x,w});
              for(int i=1,x,y,w;i<=m2;i++)scanf("%d%d%d",&x,&y,&w),G[x].push_back({y,-w});
              if(spfa())printf("YES\n");
              else printf("NO\n");
          }
          return 0;
      }
      
      • 1

      D03 D113【最短路:spfa判断负环】混合图判断负环[USACO06DEC] Wormholes G

      信息

      ID
      2246
      时间
      1000ms
      内存
      128MiB
      难度
      6
      标签
      递交数
      119
      已通过
      39
      上传者