• 【模板】SPFA判负环(洛谷P3385)


    Description

      给定一个n个点m条边有向图,每条边有一个权值,试判断图中是否存在负环。

    Input

      第一行一个正整数T表示数据组数,对于每组数据
      第一行两个正整数N M,表示图有N个顶点,M条边
      接下来M行,每行三个整数a b w,表示a->b有一条权值为w的边(若w<0则为单向,否则双向)

    Output

      共T行。对于每组数据,存在负环则输出一行"YE5"(不含引号),否则输出一行"N0"(不含引号)。

    Solution

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    #define ll long long
    #define N 2010
    #define M 6010
    using namespace std;
    int cnt,head[N],vet[M],len[M],nxt[M],Vis[N];
    int vis[N],dis[N],T,n,m,inque[N];
    queue <int> Q;
    inline ll read()
    {
        ll ans=0,f=1;
        char ch=getchar();
        while (ch<'0' || ch>'9')
        {
            if (ch=='-') f=-1;
            ch=getchar();
        }
        while (ch>='0' && ch<='9')
        {
            ans=ans*10+ch-'0';
            ch=getchar();
        }
        return ans*f;
    }
    void init()
    {
        cnt=0;
        memset(head,0,sizeof(head));
        memset(vis,0,sizeof(vis));
        memset(Vis,0,sizeof(Vis));
        memset(inque,0,sizeof(inque));
        memset(dis,0x7f7f7f7f,sizeof(dis));
    }
    void addedge(int u,int v,int l)
    {
        nxt[++cnt]=head[u];vet[cnt]=v;len[cnt]=l;head[u]=cnt;
    }
    bool SPFA(int u)
    {
        while (!Q.empty()) Q.pop();
        Q.push(u);dis[u]=0;vis[u]=1;
        while (!Q.empty())
        {
            int u=Q.front();
            Q.pop();
            Vis[u]=1;vis[u]=0;
            for (int i=head[u];i;i=nxt[i])
            {
                int v=vet[i];
                if (dis[u]+len[i]<dis[v])
                {
                    dis[v]=dis[u]+len[i];
                    if (!vis[v])
                    {
                        vis[v]=1;
                        Q.push(v);
                        inque[v]++;
                        if (inque[v]>=n) return 1;
                    }
                }
            }
        }
        return 0;
    }
    int main()
    {
     	T=read();
        while (T--)
        {
            init();
            n=read(),m=read();
            for (int i=1;i<=m;i++)
            {
                int u=read(),v=read(),w=read();
                if (w>=0) addedge(u,v,w),addedge(v,u,w);
                else addedge(u,v,w);
            }
            bool flag=0;
            for (int i=1;i<=n;i++)
            {
                if (Vis[i]) continue;
                if (SPFA(i))
                {
                    flag=1;
                    break;
                }
            }
            if (!flag) printf("N0
    "); else printf("YE5
    ");
        }
        return 0;	
    }
    
  • 相关阅读:
    349. 两个数组的交集
    383. 赎金信
    242. 有效的字母异位词
    844. 比较含退格的字符串
    904. 水果成篮
    剑指offer(9)变态跳台阶
    剑指offer(8)跳台阶
    剑指offer(7)斐波那契数列
    剑指offer(6)旋转数组的最小数字
    剑指offer(5)用两个栈实现队列
  • 原文地址:https://www.cnblogs.com/Code-Geass/p/9745094.html
Copyright © 2020-2023  润新知