杭电-1317 XYZZY(最短路+正向环)

来源:互联网 发布:linux 查看显卡型号 编辑:程序博客网 时间:2024/06/04 19:40

XYZZY

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 1701    Accepted Submission(s): 419
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
50 1 2-60 1 3-60 1 420 1 50 050 1 220 1 3-60 1 4-60 1 50 050 1 221 1 3-60 1 4-60 1 50 050 1 220 2 1 3-60 1 4-60 1 50 0-1
 
Sample Output
hopelesshopelesswinnablewinnable
 题意:从第一个房间开始有100的初始能量。每经过一个房间加上此房间的能量值,如果能量为负或者到达终点则停止。问能不能到达终点。
题解:首先先用Floyd判断连通性,如果不连通则结束。如果联通用spfa判断有没有正环,即cnt[v]>=n则有正环,有正环判断环上一点到终点是否联通。没有环的话,则判断到达终点最长的通路能量值是否大于0即可。
#include<stdio.h>#include<string.h>#include<algorithm>#define INF 0xffffusing namespace std;int w[110][110]; // 判断图的连通性int en[110]; //进入该点的能量值int d[110];  //每一点的能量值int n,m; //n 个点, m 条边struct Edge{    int u,v;} edge[110*110];void floyd() // 有向图的传递闭包{    for(int k = 1; k <= n; k++)        for(int i = 1; i <= n; i++)            for(int j = 1; j <= n; j++)                w[i][j] = w[i][j] || (w[i][k] && w[k][j]);   //初始化是0,连接是1;不能用和,只能与或;不要写错了 WA 的都是泪。。。}bool Bellman_ford(){    for(int i = 2; i <= n; i++) {d[i] = -INF;}    d[1] = 100; // 初始第一个点有 100 个能量    for(int i = 1; i < n; i++)    {        for(int j = 0; j < m; j++)        {            int u = edge[j].u;            int v = edge[j].v;            if(d[v] < d[u]+en[v] && d[u]+en[v] > 0) //松弛                d[v] = d[u]+en[v]; //是加上点的权。。。        } //注意:不能像以前一样不能松弛了,就直接返回 false 因为判断正环的目的是使 d[n] > 0    }    for(int i = 0; i < m; i++)    {        int u = edge[i].u;        int v = edge[i].v;        if(d[v] < d[u]+en[v] && d[u]+en[v] > 0) //如果存在正环            if(w[v][n]) //正环中的点能够到达终点                return true;    }    return d[n]>0; // 不存在正环, 判断能否依靠 100 个能量值到达终点}int main(){    while(scanf("%d", &n) != EOF)    {        if(n == -1) break;        m = 0; // 初始化边        memset(w, 0, sizeof(w));        memset(en, 0, sizeof(en));        for(int i = 1; i <= n; i++)    w[i][i] = 1;        int num;        for(int i = 1; i <= n; i++)        {            int v;            scanf("%d%d", &en[i], &num);            while(num--) //注意是单向的            {                scanf("%d", &v);                edge[m].u = i;                edge[m++].v = v;                w[i][v] = 1;             }        }        floyd(); // 考查有向图的连通性        if(Bellman_ford())    printf("winnable\n");        else    printf("hopeless\n");    }    return 0;}

0 0
原创粉丝点击