zoukankan      html  css  js  c++  java
  • POJ 3259 Wormholes ( SPFA判断负环 && 思维 )

    题意 : 给出 N 个点,以及 M 条双向路,每一条路的权值代表你在这条路上到达终点需要那么时间,接下来给出 W 个虫洞,虫洞给出的形式为 A B C 代表能将你从 A 送到 B 点,并且回到 C 个时间点之前,也就是时光倒流了 C 个时间并且此时你在 B 点,现在问你是否能够在图上的这些点中走,使得在某一个点刚好碰到之前的自己

    分析 : 冷静分析一下,只要是有负权回路的某一条边属于虫洞的,那么肯定是能在这个环上一直绕,直到遇到之前的自己,如果将虫洞看作一条负权边的话,那么问题就变成了只要存在负环,那么肯定是能够通过负环回路达到见到过去的自己这种操作的,用SPFA判一下就OK了!最好自己好好分析一下,为什么只要环上有虫洞就能达到目的,这个证明是很重要的!

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <queue>
    #include <string.h>
    using namespace std;
    
    const int INF=0x3f3f3f3f;
    const int maxn = 505;
    
    struct EdgeNode{ int v, w, nxt; };
    EdgeNode Edge[maxn*maxn];
    bool vis[maxn];
    int Head[maxn], Dis[maxn], cnt;
    int N, M;
    int PushCnt[maxn]; ///记录每一个节点的入队次数、方便判断负环
    
    inline void init()
    {
        for(int i=0; i<=N; i++)
            PushCnt[i] = 0,
            Head[i] = -1,
            Dis[i]  = INF,
            vis[i]  = false;
        cnt = 0;
    }
    
    inline void AddEdge(int from, int to, int weight)
    {
        Edge[cnt].w = weight;
        Edge[cnt].v = to;
        Edge[cnt].nxt = Head[from];
        Head[from] = cnt++;
    }
    
    bool SPFA(int st)///若要判断负环、改为 bool
    {
        deque<int> que;
        que.push_back(st);
        vis[st]=true;
        Dis[st]=0;
        while (!que.empty())
        {
            int T=que.front(); que.pop_front();
            vis[T]=false;
            for (int i=Head[T]; i!=-1; i=Edge[i].nxt)
            {
                int v=Edge[i].v;
                int w=Edge[i].w;
                if (Dis[v]>Dis[T]+w){
                    Dis[v]=Dis[T]+w;
                    if (!vis[v]){
                        if(++PushCnt[v] > N) return false; //有负环
                        vis[v]=true;
                        if(!que.empty() && Dis[v] < Dis[que.front()]) que.push_front(v);
                        else que.push_back(v);
                    }
                }
            }
        }
        return true;
    }
    
    
    int main(void)
    {
        int nCase, W;
        scanf("%d", &nCase);
        while(nCase--){
            scanf("%d %d %d", &N, &M, &W);
            init();
            int from, to, weight;
            for(int i=0; i<M; i++){
                scanf("%d %d %d", &from, &to, &weight);
                AddEdge(from, to, weight);
                AddEdge(to, from, weight);
            }
            for(int i=0; i<W; i++){
                scanf("%d %d %d", &from, &to, &weight);
                AddEdge(from, to, -weight);
            }
            SPFA(1)?puts("NO"):puts("YES");
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Eular质数筛法
    质数测试
    求树的直径
    常用排序的实现方法(数据结构)
    关于整数的整数因子和问题的若干研究(数学)
    状态压缩中常用的位运算(DP)
    舞蹈链--求精密覆盖(数据结构)
    高斯消元模板,整数(数学)
    树状数组 (数据结构)
    二叉树还原--通用类型模板类(数据结构)
  • 原文地址:https://www.cnblogs.com/qwertiLH/p/7725578.html
Copyright © 2011-2022 走看看