• POJ3259 Wormholes 【spfa判负环】


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

    Wormholes
    Time Limit: 2000MS   Memory Limit: 65536K
    Total Submissions:75598   Accepted: 28136

    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.
    题目大意:n 个点, m 条双向边,代表经过所需的时间,w 条单向边,代表经过所减少的时间。问该图中是否存在负环。
    思路:
    1.简单的判环,用spfa即可,在不存在环的情况下,任意点在进行路径松弛时,最多被其他的点更新一次。那么任意点的最多入队次数只能是 n 次。当存在任何一点的入队次数大于顶点数n,即说明存在环。
    2.判负环,即路径往小松弛。判正环时,即路径往大更新。注意dis数组初始化即可。
    代码如下:
     1 #include<stdio.h>
     2 #include<queue>
     3 #include<string.h>
     4 #define mem(a, b) memset(a, b, sizeof(a))
     5 const int MAXN = 550;
     6 const int MAXM = 3000;
     7 const int inf = 0x3f3f3f3f;
     8 using namespace std;
     9 
    10 int n, m, k; //n个点 m条双向边 k个虫洞(单向边) 
    11 int head[MAXN], cnt;
    12 int vis[MAXN], num[MAXN];//num表示第i个点的入队次数 用来判断负环是否存在 
    13 int dis[MAXN], flag;
    14 queue<int> Q;
    15 
    16 struct Edge
    17 {
    18     int to, next, w;
    19 }edge[2 * MAXM];
    20 
    21 void add(int a, int b, int c)
    22 {
    23     cnt ++;
    24     edge[cnt].to = b;
    25     edge[cnt].w = c;
    26     edge[cnt].next = head[a];
    27     head[a] = cnt;
    28 }
    29 
    30 void spfa(int st)
    31 {
    32     while(!Q.empty())    Q.pop();
    33     mem(vis, 0), mem(dis, inf), mem(num, 0);
    34     Q.push(st);
    35     vis[st] = 1;
    36     num[st] = 1;
    37     dis[st] = 0;
    38     while(!Q.empty())
    39     {
    40         int a = Q.front();
    41         Q.pop();
    42         vis[a] = 0;
    43         for(int i = head[a]; i != -1; i = edge[i].next)
    44         {
    45             int to = edge[i].to;
    46             if(dis[to] > dis[a] + edge[i].w)
    47             {
    48                 dis[to] = dis[a] + edge[i].w;
    49                 if(!vis[to])
    50                 {
    51                     vis[to] = 1;
    52                     Q.push(to);
    53                     num[to] ++;
    54                     if(num[to] > n)
    55                     {
    56                         flag = 1;
    57                         break;
    58                     }
    59                 }
    60             }
    61         }
    62         if(flag)
    63             break;
    64     }
    65     if(flag)
    66         printf("YES
    ");
    67     else
    68         printf("NO
    ");
    69 }
    70 
    71 int main()
    72 {
    73     int T;
    74     scanf("%d", &T);
    75     while(T --)
    76     {
    77         cnt = 0, flag = 0, mem(head, -1);
    78         scanf("%d%d%d", &n, &m, &k);
    79         for(int i = 1; i <= m; i ++)
    80         {
    81             int a, b, c;
    82             scanf("%d%d%d", &a, &b, &c);
    83             add(a, b, c);
    84             add(b, a, c);
    85         }
    86         for(int i = 1; i <= k; i ++)
    87         {
    88             int a, b, c;
    89             scanf("%d%d%d", &a, &b, &c);
    90             add(a, b, -c);
    91         }
    92         spfa(1);
    93     }
    94     return 0;
    95 }
    POJ3259
     
  • 相关阅读:
    poj3481
    查找湖南问题
    tyvj1033
    tyvj1088
    oil倒油
    加分二叉树
    模拟题2
    模拟题3
    Free pascal中的random函数
    Spring MVC入门配置
  • 原文地址:https://www.cnblogs.com/yuanweidao/p/11479589.html
Copyright © 2020-2023  润新知