zoukankan      html  css  js  c++  java
  • LightOJ 1074 1108 1221 Bellman_Ford算法判负环

    众所周知,bellman_ford算法最常用的性质是判负环

    也可以求最短路,SPFA算法改自Bellman_Ford。


    1074 - Extended Traffic

    ((u,v))的边权是$ (b[v] - b[u])^3$,输出从顶点1到各点最短路径,因为存在负环,所以从负环到达的点的最短路是-inf。

    • 如果最短路径小于3(包括负数)输出 '?'
    • 否则输出最短路
    #include <stdio.h>
    #include <iostream>
    #include <string.h>
    #include <stdlib.h>
    #include <vector>
    #include <algorithm>
    #include <queue>
    #include <map>
    #include <stack>
    #include <string>
    #include <math.h>
    #include <bitset>
    using namespace std;
    typedef pair<int,int> P;
    typedef long long LL;
    const int INF = 0x3f3f3f3f;
    const double PI = acos(-1.0);
    const double eps = 1e-9;
    const int N = 200 + 5;
    int t, kase = 0;
    int a[N];
    struct Edge
    {
        int u,v,w;
        Edge(){}
        Edge(int a, int b, int c): u(a),v(b),w(c) {}
    };
    vector<Edge> edges;
    vector<int> G[N];
    int n,m,q,p;
    void init(int n)
    {
        edges.clear();
        for(int i = 0; i <= n; i++) G[i].clear();
    }
    void addedge(int u, int v, int w)
    {
        edges.push_back(Edge(u,v,w));
        int m = edges.size();
        G[u].push_back(m-1);
    }
    int d[N], inque[N], cnt[N], circle[N];
    
    void dfs(int u)
    {
        circle[u] = 1;
        for(int i = 0; i < G[u].size(); i++)
        {
            Edge &e = edges[G[u][i]];
            int v = e.v;
            if(circle[v]) continue;
            dfs(v);
        }
    }
    
    bool Bellman_ford(int s)
    {
        memset(d, 0x3f, sizeof(d));
        memset(cnt, 0, sizeof(cnt));
        memset(inque, 0, sizeof(inque));
        memset(circle, 0, sizeof(circle));
        d[s] = 0; inque[s] = 1;
        queue<int> Q;
        Q.push(s);
        while(!Q.empty())
        {
            int u = Q.front(); Q.pop(); inque[u] = 0;
            for(int i = 0; i < G[u].size(); i++)
            {
                Edge &e = edges[G[u][i]];
                int v = e.v;
                if(circle[v]) continue;
                if(d[v] > d[u] + e.w)
                {
                    d[v] = d[u] + e.w;
                    if(!inque[v])
                    {
                        cnt[v]++;
                        Q.push(v);
                        inque[v] = 1;
                        if(cnt[v] > n) dfs(v);
                    }
                }
            }
        }
        return true;
    }
    
    int main()
    {
        scanf("%d", &t);
        while(t--)
        {
            scanf("%d", &n);
            init(n);
            for(int i = 1; i <= n; i++)
                scanf("%d", &a[i]);
            scanf("%d", &m);
            for(int i = 0; i < m; i++)
            {
                int u, v, w;
                scanf("%d%d", &u, &v);
                w = (a[v]- a[u]);
                w = w*w*w;
                addedge(u,v,w);
            }
            Bellman_ford(1);
            scanf("%d", &q);
            printf("Case %d:
    ", ++kase);
            for(int i = 0; i < q; i++)
            {
                scanf("%d", &p);
                if(circle[p] || d[p] == INF || d[p] < 3)
                    printf("?
    ");
                else
                    printf("%d
    ", d[p]);
            }
        }
        return 0;
    }
    

    1108 - Instant View of Big Bang

    穿越回去看大爆炸,找到可以通往负环的点作为起点,并将起点列出来。

    思路

    可以将图反过来建,就转变成了可以从负环走到的点,跟上题一样。

    #include <stdio.h>
    #include <iostream>
    #include <string.h>
    #include <stdlib.h>
    #include <vector>
    #include <algorithm>
    #include <queue>
    #include <map>
    #include <stack>
    #include <string>
    #include <math.h>
    #include <bitset>
    using namespace std;
    typedef pair<int,int> P;
    typedef long long LL;
    const int INF = 0x3f3f3f3f;
    const double PI = acos(-1.0);
    const double eps = 1e-9;
    const int N = 1000 + 5;
    int t, kase = 0;
    struct Edge
    {
        int u,v,w;
        Edge(){}
        Edge(int a, int b, int c): u(a),v(b),w(c) {}
    };
    vector<Edge> edges;
    vector<int> G[N];
    int n,m;
    void init(int n)
    {
        edges.clear();
        for(int i = 0; i <= n; i++) G[i].clear();
    }
    void addedge(int u, int v, int w)
    {
        edges.push_back(Edge(u,v,w));
        int m = edges.size();
        G[u].push_back(m-1);
    }
    int d[N], inque[N], cnt[N], circle[N];
    
    void dfs(int u)
    {
        circle[u] = 1;
        for(int i = 0; i < G[u].size(); i++)
        {
            Edge &e = edges[G[u][i]];
            int v = e.v;
            if(circle[v]) continue;
            dfs(v);
        }
    }
    
    bool Bellman_ford(int s)
    {
        queue<int> Q;
        for(int i = 0; i < n; i++)
        {
            d[i] = cnt[i] = 0;
            inque[i] = 1;
            circle[i] = 0;
            Q.push(i);
        }
        while(!Q.empty())
        {
            int u = Q.front(); Q.pop(); inque[u] = 0;
            for(int i = 0; i < G[u].size(); i++)
            {
                Edge &e = edges[G[u][i]];
                int v = e.v;
                if(circle[v]) continue;
                if(d[v] > d[u] + e.w)
                {
                    d[v] = d[u] + e.w;
                    if(!inque[v])
                    {
                        cnt[v]++;
                        Q.push(v);
                        inque[v] = 1;
                        if(cnt[v] > n) dfs(v);
                    }
                }
            }
        }
        return true;
    }
    int u,v,w;
    int main()
    {
        scanf("%d", &t);
        while(t--)
        {
            scanf("%d%d", &n, &m);
            init(n);
            for(int i = 0; i < m; i++)
            {
                scanf("%d%d%d", &u, &v, &w);
                addedge(v, u, w);
            }
            Bellman_ford(0);
            printf("Case %d:", ++kase);
            int f = 0;
            for(int i = 0; i < n; i++)
                if(circle[i])
                {
                    printf(" %d", i);
                    f = 1;
                }
            if(f == 0)
                printf(" impossible");
            printf("
    ");
        }
        return 0;
    }
    

    1221 - Travel Company

    旅游公司规划旅游路线,要求走完一条路线后 总收入/总支出 > p,转化一下就是

    [in[0] + in[1] + cdots + in[k] > p imes(out[0]+out[2]+cdots+out[k]) ]

    [in[0] + in[1] + cdots + in[k] > p imes out[0]+ p imes out[2]+ cdots+ p imes out[k] ]

    [(p imes out[0] - in[0])+ (p imes out[1] - in[1]) + cdots + (p imes out[k] - in[k]) < 0 ]

    就直接令(w = out*p - in) 最后结出现一个负环即可

    #include <stdio.h>
    #include <iostream>
    #include <string.h>
    #include <stdlib.h>
    #include <vector>
    #include <algorithm>
    #include <queue>
    #include <map>
    #include <stack>
    #include <string>
    #include <math.h>
    #include <bitset>
    using namespace std;
    typedef pair<int,int> P;
    typedef long long LL;
    const int INF = 0x3f3f3f3f;
    const double PI = acos(-1.0);
    const double eps = 1e-9;
    const int N = 1000 + 5;
    int t, kase = 0;
    int n,m,p;
    struct Edge
    {
        int u,v,w;
        Edge(){}
        Edge(int a, int b, int c): u(a), v(b), w(c) {}
    };
    vector<Edge> edges;
    vector<int> G[N];
    void init(int n)
    {
        edges.clear();
        for(int i = 0; i <= n; i++) G[i].clear();
    }
    void addedge(int u, int v, int w)
    {
        edges.push_back(Edge(u, v, w));
        int m = edges.size();
        G[u].push_back(m-1);
    }
    int cnt[N], inque[N], d[N];
    bool Bellman_ford()
    {
        queue<int> Q;
        for(int i = 0; i < n; i++)
        {
            inque[i]= 1;
            d[i] = 0;
            cnt[i] = 0;
            Q.push(i);
        }
        while(!Q.empty())
        {
            int u = Q.front(); Q.pop(); inque[u] = 0;
            for(int i = 0; i < G[u].size(); i++)
            {
                Edge &e = edges[G[u][i]];
                int v = e.v;
                if(d[v] > d[u] + e.w)
                {
                    d[v] = d[u] + e.w;
                    if(!inque[v])
                    {
                        inque[v] = 1;
                        cnt[v]++;
                        Q.push(v);
                        if(cnt[v] > n)
                            return false;
                    }
                }
            }
        }
        return true;
    }
    
    int main()
    {
        scanf("%d", &t);
        while(t--)
        {
            scanf("%d%d%d", &n, &m, &p);
            init(n);
            for(int i = 0; i < m; i++)
            {
                int u,v,in,out,w;
                scanf("%d%d%d%d", &u, &v, &in, &out);
                w = p*out - in;
                addedge(u, v, w);
            }
            printf("Case %d: ", ++kase);
            if(!Bellman_ford())
                printf("YES
    ");
            else
                printf("NO
    ");
        }
        return 0;
    }
    
    如果有错误,请指出,谢谢
  • 相关阅读:
    第05组 Beta版本演示
    第05组 Beta冲刺(4/4)
    第05组 Beta冲刺(3/4)
    第05组 Beta冲刺(2/4)
    第05组 Beta冲刺(1/4)
    第05组 Alpha事后诸葛亮
    第05组 Alpha冲刺(4/4)
    第05组 Alpha冲刺(3/4)
    第05组 Alpha冲刺(2/4)
    300iq Contest 3 C. Cells Blocking
  • 原文地址:https://www.cnblogs.com/Alruddy/p/7398461.html
Copyright © 2011-2022 走看看