• HDU 1373 XYZZY (spfa的特殊用法)


    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1317

    题目大意:有n个房间,编号1~n,房间之间有单向门连接。某人初始位于1号房间,且具有100点能量。此人要去n号房间,中途每经到一个房间Ri,其能量值会加上一个值ai,当其能量值小于等于0的时候会死掉。问此人能否到达n号房间。n<100, -100 <= ai <= 100。

    分析:将房间看做结点,单向门看成单向边,形成一张有向图,问题转换为搜索一条从1号点能到达n号点的路径。

      使用SPFA算法搜索最长路。如果图中不存在环,则找一条最长路即可。

      否则,存在负环不影响结果。

      如果存在正环,在顶点第n次进队列的时候,距离标记成无穷大,之后不在进队。这样,只要存在合理的路径,就一定能到达n点,不能到达说明无解。

    参考代码:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <vector>
     4 using namespace std;
     5 #define N 110
     6 #define inf 1000000000
     7 
     8 vector<int>ve[N];
     9 
    10 int w[N];
    11 int Q[N*N];
    12 bool inq[N];
    13 int dis[N], cnt[N];
    14 int id;
    15 bool spfa(int n)
    16 {
    17     for(int i = 1; i <= n; i++)
    18     {
    19         dis[i] = -inf, inq[i] = 0, cnt[i] = 0;
    20     }
    21     dis[1] = 100;
    22     int top = 0;
    23     Q[top++] = 1;
    24     inq[1] = cnt[1] = 1;
    25     for(int i = 0; i < top; i++)
    26     {
    27         int u = Q[i];
    28         inq[u] = 0;
    29         if(dis[u]+w[u] <= 0) continue;
    30         int m = ve[u].size();
    31         for(int j = 0; j < m; j++)
    32         {
    33             int v = ve[u][j];
    34             if(dis[v] < dis[u] + w[u])
    35             {
    36                 dis[v] = dis[u] + w[u];
    37                 if(v == n) return true;
    38                 if(!inq[v])
    39                 {
    40                     cnt[v]++;
    41                     if(cnt[v] > n) continue;
    42                     if (cnt[v] == n) 
    43                         dis[v] = inf;
    44                     Q[top++] = v;
    45                     inq[v] = 1; 
    46                 }
    47             }
    48         }
    49     }
    50     return false;
    51 }
    52 int main()
    53 {
    54     int n;
    55     while(~scanf("%d", &n), ~n)
    56     {
    57         for(int i = 1; i <= n; i++) ve[i].clear();
    58         for(int i = 1; i <= n; i++)
    59         {
    60             int m, t;
    61             scanf("%d", &w[i]);
    62             scanf("%d", &m);
    63             for(int j = 0; j < m; j++)
    64             {
    65                 scanf("%d", &t);
    66                 ve[i].push_back(t);
    67             }
    68         }
    69         bool res = spfa(n);
    70         if(res) puts("winnable");
    71         else puts("hopeless");
    72     }
    73     return 0;
    74 }
  • 相关阅读:
    repr() Vs str()
    默认参数
    元组
    字典
    电脑可以办的两类最基本的事情
    代码块
    变量名
    print的逻辑
    input的逻辑
    让python2听懂中文
  • 原文地址:https://www.cnblogs.com/beisong/p/4710893.html
Copyright © 2020-2023  润新知