• 负环--spfa


    洛谷板子题

    负环?是有负权边的环还是一个边权之和为负的环?

    还没有准确的定义(那就先忽略吧qwq

    判断负环的方法:

    暴力枚举/spfa/mellman—ford/奇怪的贪心/超神的搜索

    可惜我只会spfa

    spfa:垂死病中惊坐起

    有两种spfa可以用来求负环:dfs和bfs

    在求负环上bfs要更好一些,dfs稍逊色一些

    (注意:要memset,变量类型定义的时候要细致一些)

    //bfs版spfa 
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    #define ll long long
    using namespace std;
    
    inline ll read()
    {
        ll sum = 0, p = 1;
        char ch = getchar();
        while(ch < '0' || ch > '9')
        {
            if(ch == '-')
                p = -1;
            ch = getchar();
        }
        while(ch >= '0' && ch <= '9')
        {
            (sum *= 10) += ch - '0';
            ch = getchar();
        }
        return sum * p;
    }
    
    const int maxn = 2005,maxm = 3005;
    struct edge
    {
        int nxt,to;
        ll wei;
    } e[maxm * 2];
    int t,n,m,tot,cnt[maxn],head[maxn],dis[maxn];
    bool vis[maxn];
    
    void add(int a,int b,ll c)
    {
        e[++tot].nxt = head[a];
        e[tot].to = b;
        e[tot].wei = c;
        head[a] = tot;
    }
    
    bool spfa(int x)
    {
        queue<int> q;
        for(int i = 1; i <= n; i++)
            dis[i] = 1e9;
        vis[x] = true;
        q.push(x);
        cnt[x]++;
        dis[x] = 0;
        while(!q.empty())
        {
            int u = q.front();
            q.pop();
            vis[u] = false;
            if(cnt[u] >= n)
                return true;
            for(int i = head[u]; i; i = e[i].nxt)
            {
    
                int v = e[i].to;
                if(dis[v] > dis[u] + e[i].wei)
                {
                    dis[v] = dis[u] + e[i].wei;
                    if(!vis[v])
                    {
                        vis[v] = true;
                        q.push(v);
                        cnt[v] ++;
                        if(cnt[v] >= n)
                            return true;
                    }
                }
            }
        }
        return false;
    }
    
    int main()
    {
        t = read();
        while(t--)
        {
            n = read(),m = read();
            tot = 0;
            memset(e,0,sizeof(e));
            memset(dis,0,sizeof(dis));
            memset(head,0,sizeof(head));
            memset(vis,false,sizeof(vis));
            memset(cnt,0,sizeof(cnt));
            int a,b,c;
            for(int i = 1; i <= m; i++)
            {
                a = read(),b = read(),c = read();
                add(a,b,c);
                if(c >= 0)
                    add(b,a,c);
            }
            if(spfa(1))
                printf("YE5
    ");
            else
                printf("N0
    ");
        }
        return 0;
    }
    //dfs版spfa 
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    
    inline int read()
    {
        int sum = 0, p = 1;
        char ch = getchar();
        while(ch < '0' || ch > '9')
        {
            if(ch == '-')
                p = -1;
            ch = getchar();
        }
        while(ch >= '0' && ch <= '9')
        {
            (sum *= 10) += ch - '0';
            ch = getchar();
        }
        return sum * p;
    }
    
    const int maxn = 2005,maxm = 3005;
    bool flag,vis[maxn];
    int n,m,t;
    int head[maxn],dis[maxn],cnt;
    struct edge
    {
        int nxt,to,wei;
    }e[maxm * 2];
    
    void add(int a,int b,int c)
    {
        e[++cnt].nxt = head[a];
        e[cnt].to = b;
        e[cnt].wei = c;
        head[a] = cnt;
    }
    
    void spfa(int x)
    {
        vis[x] = true;
        for(int i = head[x];i;i = e[i].nxt)
        {
            int v = e[i].to;
            if(dis[v] > dis[x] +e[i].wei)
            {
                if(vis[v] || flag)
                {
                    flag = true;
                    break;
                }
                dis[v] = dis[x] +e[i].wei;
                spfa(v);
            }
        }
        vis[x] = false;
    }
    
    int main()
    {
        t = read();
        while(t--)
        {
            cnt = 0;
            flag = 0;
            memset(head,0,sizeof(head));
            memset(dis,0,sizeof(dis));
            memset(e,0,sizeof(e));
            memset(vis,false,sizeof(vis));
            n = read(),m = read();
            int a,b,c;
            for(int i = 1;i <= m;i++)
            {
                a = read(),b = read(),c = read();
                add(a,b,c);
                if(c >= 0)
                    add(b,a,c);
            }
            for(int i = 1;i <= n;i++)
            {
                spfa(i);
                if(flag)
                    break;
            }
            if(flag)
                printf("YE5
    ");
            else
                printf("N0
    ");
        }
        return 0;
    } 
  • 相关阅读:
    360随身WiFi使用问题解决,无法在没有网络的电脑上使用
    np问题(大数阶乘取模)
    传球(概率问题)
    区间平均值(逆序对)
    完全平方数最大
    计算毫秒
    祖玛游戏
    后缀最大值
    Blah数集(双指针单调队列)
    逢低吸纳(最长下降子序列+方案数+高精度)
  • 原文地址:https://www.cnblogs.com/darlingroot/p/11224558.html
Copyright © 2020-2023  润新知