hdu-1317-XYZZY-Bellman-Ford判環、Floyd算法

Link:

http://acm.hdu.edu.cn/showproblem.php?pid=1317

XYZZY

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 4368    Accepted Submission(s): 1234

Problem Description

  It has recently been discovered how to run open-source software on the Y-Crate gaming device. A number of enterprising designers 
  have developed Advent-style games for deployment on the Y-Crate. Your job is to test a number of these designs to see which are 
  winnable. 
  Each game consists of a set of up to 100 rooms. One of the rooms is the start and one of the rooms is the finish. Each room has 
  an energy value between -100 and +100. One-way doorways interconnect pairs of rooms. 

  The player begins in the start room with 100 energy points. She may pass through any doorway that connects the room she is in 
  to another room, thus entering the other room. The energy value of this room is added to the player's energy. This process 
  continues until she wins by entering the finish room or dies by running out of energy (or quits in frustration). During her 
  adventure the player may enter the same room several times, receiving its energy each time. 

Input

  The input consists of several test cases. Each test case begins with n, the number of rooms. The rooms are 
  numbered from 1 (the start room) to n (the finish room). Input for the n rooms follows. The input for each room consists of 
  one or more lines containing: 

  the energy value for room i 
  the number of doorways leaving room i 
  a list of the rooms that are reachable by the doorways leaving room i 
  The start and finish rooms will always have enery level 0. A line containing -1 follows the last test case. 

Output

  In one line for each case, output "winnable" if it is possible for the player to win, otherwise output "hopeless". 

Sample Input

5
0 1 2
-60 1 3
-60 1 4
20 1 5
0 0
5
0 1 2
20 1 3
-60 1 4
-60 1 5
0 0
5
0 1 2
21 1 3
-60 1 4
-60 1 5
0 0
5
0 1 2
20 2 1 3
-60 1 4
-60 1 5
0 0
-1

Sample Output

hopeless
hopeless
winnable
winnable

Source

University of Waterloo Local Contest 2003.09.27

解釋

    上圖我們分別考慮n=6和n=7兩種情況這兩種特例。

    我們考慮一下首先必須從1可以到達n,暫且不考慮能量問題,也就是說首先1,n必須連通,然後我們考慮如果是無環的話,必須到達
    n點能量仍然保持正數。如果有環,負環的話我們完全可以不用考慮,如果有正環並且可以到達,那麼只要環上的點可以到達n,那麼必然可以,我們
    便想到了Bellman-Ford算法和Floyd算法。

Code

#include <cstdio>
#include <cstring>
using namespace std;
const int maxn(105);
const int INF(0x3f3f3f3f);
int map[maxn][maxn];/******用於判斷圖上的任意兩個端點是否連通*******/
int n;
int room_energy[maxn];
int edge_index;/*****存儲這個圖開始時給出的邊的個數******/
struct edge
{
    int from,to;
} edges[maxn*maxn];
void init()
{
    memset(map,0,sizeof(map));
    for(int i=1; i<=n; i++)
        map[i][i]=1;
    edge_index=0;
}
void input()
{
    int cnt_next,_next;
    for(int i=1; i<=n; i++)
    {
        scanf("%d%d",room_energy+i,&cnt_next);
        while(cnt_next--)
        {
            scanf("%d",&_next);
            map[i][_next]=1;
            ++edge_index;
            edges[edge_index].from=i;
            edges[edge_index].to=_next;
        }
    }
}
void floyd()/******Floyd算法用於判定任意兩點的連通**********/
{
    for(int i=1; i<=n; i++)/******Floyd算法注意i,j,k的位置,不能顛倒*******/
    {
        for(int j=1; j<=n; j++)
        {
            for(int k=1; k<=n; k++)
            {
                map[i][j]=map[i][j]||(map[i][k]&&map[k][j]);
            }
        }
    }
}
bool bellman_ford()
{
    int dis[maxn];
    for(int i=2; i<=n; i++)
    {
        dis[i]=-INF;
    }
    dis[1]=100;
    int from,to;
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=edge_index; j++)
        {
            from=edges[j].from;
            to=edges[j].to;
            /****注意此處dis[from]+room_energy[to]>0的意思是還沒有run out of energy****/
            if(dis[to]<dis[from]+room_energy[to]&&dis[from]+room_energy[to]>0)
            {
                dis[to]=dis[from]+room_energy[to];
            }
        }
    }
    for(int i=1; i<=edge_index; i++)
    {
        from=edges[i].from;
        to=edges[i].to;
        if(dis[to]<dis[from]+room_energy[to]&&dis[from]+room_energy[to]>0&&map[to][n])
            return 1;/*****若有環的地方可以與終點連通那麼必然可以******/
    }
    return dis[n]>0;/****沒遇到環但是能量沒有耗光****/
}
int main()
{
    while(scanf("%d",&n),n!=-1)
    {
        init();
        input();
        floyd();
        if(!map[1][n])/********如果開始點與最後的點都不連通,那麼必定不可能**********/
        {
            puts("hopeless");
            continue;
        }
        if(bellman_ford())
            puts("winnable");
        else
            puts("hopeless");
    }
    return 0;
}
發佈了37 篇原創文章 · 獲贊 6 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章