zoukankan      html  css  js  c++  java
  • 题解 UVA11721 Instant View of Big Bang(SPFA建反图判负环)

    题意

    给出一张n ((nleq1000)) 点m ((mleq2000)) 边的有向图,要求判断负环,并升序输出可以到负环的点
    (多组数据 (Tleq125));

    算法

    建反图 + SPFA判负环 + dfs染色

    思路

    当建完反图后,负环是不变的,原图上所有能到负环的点在反图上变成了负环能到的点,因此只需找出负环上的点,dfs染色即可

    代码

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int maxn = 2e4 + 10;
    int n,m,head[maxn],num,flag,dis[maxn],vis[maxn],mark[maxn],cnt[maxn];
    struct Edge{
        int then,to,val;
    }e[maxn];
    
    void add(int u, int v, int val){e[++num] = (Edge){head[u], v, val}; head[u] = num;}
    
    void dfs(int p){
        mark[p] = 1;
        for(int i = head[p]; i; i = e[i].then){
            int v = e[i].to;
            if(!mark[v]) dfs(v);
        }
    }
    
    void SPFA(int st){
        queue<int> q;
        memset(dis,0x3f3f3f3f,sizeof(dis));
        memset(vis,0,sizeof(vis));
        memset(cnt,0,sizeof(cnt));
        dis[st] = 0; vis[st] = 1; q.push(st);
        while(!q.empty()){
            int u = q.front();
            q.pop(); vis[u] = 0;
            for(int i = head[u]; i; i = e[i].then){
                int v = e[i].to;
                if(mark[v]) continue;
                if(dis[v] > dis[u] + e[i].val){
                    dis[v] = dis[u] + e[i].val;
                    if(!vis[v]){
                        cnt[v] ++;
                        if(cnt[v] > n) flag = 1, dfs(v);  
                        //注意:这里是 >n 而不是 >=n 例如:只有一个点时
                        q.push(v);
                        vis[v] = 1;
                    }
                }
            }
        }
    }
    
    int main(){
        int T;
        scanf("%d", &T);
        for(int t = 1; t <= T; ++ t){
            num = 0; flag = 0;
            memset(head,0,sizeof(head));
            memset(mark,0,sizeof(mark));
            scanf("%d%d", &n, &m);
            for(int i = 1; i <= m; ++ i){
                int u,v,val;
                scanf("%d%d%d", &u, &v, &val);
                add(v, u, val);
            }
            for(int i = 0; i < n; ++ i) add(n, i, 0);
            SPFA(n);
            printf("Case %d:", t);
            if(!flag) printf(" impossible
    ");  //注意空格,换行
            else{
                for(int i = 0; i < n; ++ i)
                    if(mark[i]) printf(" %d", i);
                printf("
    ");
            }
        }
        return 0;
    }
    
  • 相关阅读:
    java_泛型
    java工具类Collections
    Map集合的遍历
    集合元素顺序的实现
    apk比较版本大小
    存储过程与SQL语句怎么选择
    线程协作-生产者/消费者问题
    线程中断、线程让步、线程睡眠、线程合并
    如何将字符串去重复demo工具
    JavaScript 中的函数介绍
  • 原文地址:https://www.cnblogs.com/whenc/p/13790018.html
Copyright © 2011-2022 走看看