• POJ3259 Wormholes —— spfa求负环


    题目链接:http://poj.org/problem?id=3259

    Wormholes
    Time Limit: 2000MS   Memory Limit: 65536K
    Total Submissions: 55082   Accepted: 20543

    Description

    While exploring his many farms, Farmer John has discovered a number of amazing wormholes. A wormhole is very peculiar because it is a one-way path that delivers you to its destination at a time that is BEFORE you entered the wormhole! Each of FJ's farms comprises N (1 ≤ N ≤ 500) fields conveniently numbered 1..NM (1 ≤ M ≤ 2500) paths, and W (1 ≤ W ≤ 200) wormholes.

    As FJ is an avid time-traveling fan, he wants to do the following: start at some field, travel through some paths and wormholes, and return to the starting field a time before his initial departure. Perhaps he will be able to meet himself :) .

    To help FJ find out whether this is possible or not, he will supply you with complete maps to F (1 ≤ F ≤ 5) of his farms. No paths will take longer than 10,000 seconds to travel and no wormhole can bring FJ back in time by more than 10,000 seconds.

    Input

    Line 1: A single integer, FF farm descriptions follow. 
    Line 1 of each farm: Three space-separated integers respectively: NM, and W 
    Lines 2..M+1 of each farm: Three space-separated numbers (SET) that describe, respectively: a bidirectional path between S and E that requires T seconds to traverse. Two fields might be connected by more than one path. 
    Lines M+2..M+W+1 of each farm: Three space-separated numbers (SET) that describe, respectively: A one way path from S to E that also moves the traveler back T seconds.

    Output

    Lines 1..F: For each farm, output "YES" if FJ can achieve his goal, otherwise output "NO" (do not include the quotes).

    Sample Input

    2
    3 3 1
    1 2 2
    1 3 4
    2 3 1
    3 1 3
    3 2 1
    1 2 3
    2 3 4
    3 1 8

    Sample Output

    NO
    YES

    Hint

    For farm 1, FJ cannot travel back in time. 
    For farm 2, FJ could travel back in time by the cycle 1->2->3->1, arriving back at his starting location 1 second before he leaves. He could start from anywhere on the cycle to accomplish this.

    Source

     
     
     
     
    题解:
    当能够最终回到初始位置,并且时间倒退,满足以下两种情况之一:
    1.用spfa求出了负环,并且初始点在环内。此种情况理所当然地符合条件。
    2.用spfa求出了负环,然而初始点不在环内。那么:可以在这个环内兜转无数次,时间无限倒退,然后再花费一定的代价(有可能是时间前进,也有可能是时间倒退)回到初始位置。
    综上:只要能求出负环,就能满足要求。
     
     
     
    代码如下:
      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #include <vector>
      6 #include <cmath>
      7 #include <queue>
      8 #include <stack>
      9 #include <map>
     10 #include <string>
     11 #include <set>
     12 #define rep(i,a,n) for(int (i) = a; (i)<=(n); (i)++)
     13 #define ms(a,b) memset((a),(b),sizeof((a)))
     14 using namespace std;
     15 typedef long long LL;
     16 const double EPS = 1e-8;
     17 const int INF = 2e9;
     18 const LL LNF = 9e18;
     19 const int MOD = 1e9+7;
     20 const int MAXN = 1e3+10;
     21 
     22 int N, M, W;
     23 
     24 struct edge
     25 {
     26     int to, w, next;
     27 }edge[MAXN*MAXN];
     28 int cnt, head[MAXN];
     29 
     30 void add(int u, int v, int w)
     31 {
     32     edge[cnt].to = v;
     33     edge[cnt].w = w;
     34     edge[cnt].next = head[u];
     35     head[u] = cnt++;
     36 }
     37 
     38 void init()
     39 {
     40     cnt = 0;
     41     memset(head, -1, sizeof(head));
     42 }
     43 
     44 int dis[MAXN], times[MAXN], inq[MAXN];
     45 bool spfa(int st)
     46 {
     47     memset(inq, 0, sizeof(inq));
     48     memset(times, 0, sizeof(times));
     49     for(int i = 1; i<=N; i++)
     50         dis[i] = INF;
     51 
     52     queue<int>Q;
     53     Q.push(st);
     54     inq[st] = 1;
     55     dis[st] = 0;
     56     while(!Q.empty())
     57     {
     58         int u = Q.front();
     59         Q.pop(); inq[u] = 0;
     60         for(int i = head[u]; i!=-1; i = edge[i].next)
     61         {
     62             int v = edge[i].to;
     63             if(dis[v]>dis[u]+edge[i].w)
     64             {
     65                 dis[v] = dis[u]+edge[i].w;
     66                 if(!inq[v])
     67                 {
     68                     Q.push(v);
     69                     inq[v] = 1;
     70                     if(++times[v]>N) return true;
     71                 }
     72             }
     73         }
     74     }
     75     return false;
     76 }
     77 
     78 int main()
     79 {
     80     int T;
     81     scanf("%d",&T);
     82     while(T--)
     83     {
     84         init();
     85         scanf("%d%d%d", &N, &M, &W);
     86         for(int i = 1; i<=M; i++)
     87         {
     88             int s, e, t;
     89             scanf("%d%d%d", &s, &e, &t);
     90             add(s, e, t);
     91             add(e, s, t);
     92         }
     93 
     94         for(int i = 1; i<=W; i++)
     95         {
     96             int s, e, t;
     97             scanf("%d%d%d", &s, &e, &t);
     98             add(s, e, -t);
     99         }
    100 
    101         int flag = 0;
    102         for(int i = 1; i<=N; i++)
    103         if(spfa(i)) 
    104         {
    105             flag = 1;
    106             break;
    107         }
    108         
    109 
    110         if(flag)
    111             puts("YES");
    112         else
    113             puts("NO");
    114     }
    115 }
    View Code
  • 相关阅读:
    爱情三十七课,恩情仪式
    爱情三十二课,幽默的用法
    爱情四十二课,距离就是问题
    爱情二十八课,你为什么爱
    爱情三十四课,放手的时机
    爱情三十九课,爱的礼物
    爱情三十三课,读懂愤怒
    爱情三十一课,先信自己
    爱情三十课,爱情整理术
    爱情二十四课,妥协50分
  • 原文地址:https://www.cnblogs.com/DOLFAMINGO/p/7604261.html
Copyright © 2020-2023  润新知