XYZZY HDU

来源:互联网 发布:php手机网页开发 编辑:程序博客网 时间:2024/06/05 20:56
Floyd判断连通性 + spfa判断正环。
题目描述:有一百个房间,你的初始能量值是100,从起点1开始出发,判断你能不能到达第100个房间。不能到达的情况是,在中途的过程中生命值降为0及以下,或者是没有路能够到达房间100。注意:题目中是单项边。而且同一个房间可以进入多次。
解题分析:先用Floyd判断一下能否到达。如果能到达的话,看看到达终点的生命值是否大于0。因为要尽量能活到那,所以求得不是最短路了,而是最长路。所以原版的spfa的写法大于小于反过来就行。因为松弛的时候,要求得是生命值大于0,而且是求最长路,所以d[t] + pic[t][i] <= 0 的话就不会进行松弛,所以也就不存在负圈的问题了,而是存在正圈。当发现了正圈的时候不是直接返回true,我在这个地方WA了好多次,因为一旦发现了正圈则说明这个点一定能够在这个圈内,而且起点是能够到达这个点的,但是因为此题是单向边,即便有正圈,也不能确定一定能到达终点。比如说,从起点到终点
的路径中不过包含圈内的任何点的话,则即便有圈也不能确定能否到达终点。此时正确的处理应该是,判断圈内的点能否到达终点。

代码如下:

#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <queue>using namespace std;const int INF = 0x3f3f3f3f;const int maxn = 100 + 10;bool graph[maxn][maxn];int pic[maxn][maxn];int enqueue[maxn];int d[maxn];int used[maxn];int n;void init(){    memset(graph,false,sizeof(graph));    for(int i = 1; i <= n; i++)    {        for(int j = 1; j <= n; j++)        {            pic[i][j] = -INF;        }    }    memset(enqueue,0,sizeof(enqueue));    for(int i = 1; i <= n; i++) d[i] = -INF;    memset(used,0,sizeof(used));}bool spfa(){    d[1] = 100;    queue <int> q;    q.push(1);    used[1] = 1;    enqueue[1]++;    while(!q.empty())    {        int t = q.front();        q.pop();        used[t] = 0;        for(int i = 1; i <= n; i++)        {            if(pic[t][i] != -INF)            {                if(d[i] < d[t] + pic[t][i] && d[t] + pic[t][i] > 0)                {                    d[i] = d[t] + pic[t][i];                    if(!used[i])                    {                        q.push(i);                        enqueue[i]++;                        used[i] = 1;                        if(enqueue[i] > n)                        {                            return graph[i][n];                        }                    }                }            }        }    }    return d[n] > 0;}int main(){    while(cin >> n && n != -1)    {        init();        int m,y,w;        for(int i = 1; i <= n; i++)        {            cin >> w >> m;            for(int j = 0; j < m; j++)            {                cin >> y;                graph[i][y] = 1;                pic[i][y] = w;            }        }        for(int k = 1; k <= n; k++)        {            for(int i = 1; i <= n; i++)            {                for(int j = 1; j <= n; j++)                {                    graph[i][j] = graph[i][j] || graph[i][k]&&graph[k][j];                }            }        }        if(!graph[1][n]) printf("hopeless\n");        else        {            if(spfa()) printf("winnable\n");            else printf("hopeless\n");        }    }    return 0;}

在正圈那个地方WA了好多次,,智商啊。


原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 15岁怎么办银行卡淘宝 满16岁怎么办银行卡 电脑最小化后不见了怎么办 满16周岁怎么办银行卡 给儿童办身份证怎么办 当兵前身份证号码不符怎么办 身份证后六位密码x怎么办 借了贷款人死了怎么办 贷款实在还不起怎么办 个人贷款还不起怎么办 珠海派出所办事不公平怎么办 改身份证后学籍怎么办? 威海身份证丢了怎么办 车牌轻微变形了怎么办 车牌照丢一个怎么办 小车车牌掉了怎么办 车牌撞变形了怎么办 车牌烂了一块怎么办 机动车牌照丢了怎么办 汽车想换车牌怎么办 机动车前牌照丢失怎么办 汽车后牌照丢失怎么办 机动车扣分超证怎么办 联通香港无服务怎么办 长乐改区 闽侯怎么办 学校代码查不到怎么办 买票没带身份证怎么办 163邮件发错人了怎么办 pos机未到账怎么办 刷卡迟迟不到账怎么办 农行全渠道升级怎么办 手机输入身份证x怎么办 买房子没有社区怎么办 结婚没钱买房子怎么办 假离婚买房子怎么办? 微信怎么办居住证厦门 厦门没有暂住证怎么办居住证 机票上没有登机口怎么办 德国黑工怎么办居留 夏天吹空调感冒怎么办 拖鞋穿着脚臭怎么办