hdu1317 || uva 10557 - XYZZY(spfa || dfs)

题意:有N个房间,刚开始你位于1号房间,有100的能量值,你要到达N号房间,每两个房间之间有单向门相连接,你到达某个房间可以加上该房间的能量值,如果你在未到达N号房间之前能量值耗尽,则死亡,否则胜利。

spfa思路:通过不断地进行松弛操作,使得存在回路的点对应的能量值不断变大变大,或者是能量不断变大的次数超过一个给定的值(这个值要很大很大,我设置的是10000),到达终点能量依然大于0为止。到不了终点或者到终点能量值耗尽,则死亡,否则胜利。

AC代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e3;
#define inf 0x3f3f3f3f
int n,m;
int d[maxn],vis[maxn],cnt[maxn];
vector<pair<int,int> >E[maxn];
void init()
{
    for(int i = 0; i < maxn; i++) vis[i] = 0, cnt[i] = 0;
    for(int i = 0; i < maxn; i++) d[i] = 0;
    for(int i = 0; i < maxn; i++) E[i].clear();
}
void spfa()
{
    d[1] = 100; vis[1] = 1;
    queue <int> Q;
        Q.push(1);
        while(!Q.empty())
        {
            int now = Q.front();
            Q.pop(); vis[now] = 0;
            for(int j = 0; j < E[now].size(); j++)
            {
                int v = E[now][j].first;
                if(d[v] < d[now] + E[now][j].second && cnt[v] < 10000)
                {
                    cnt[v]++;
                    d[v] = d[now] + E[now][j].second;
                    if(vis[v]) continue;
                    vis[v] = 1;
                    Q.push(v);
                }
            }
        }
}
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        if(n == -1) break;
        init();
        int a,b,x;
        for(int i = 1; i <= n; i++)
        {
            scanf("%d%d",&x,&m);
            for(int j = 1; j <= m; j++)
            {
                scanf("%d",&b);
                E[i].push_back(make_pair(b,x));
            }
        }
        spfa();
        if(d[n] > 0) puts("winnable");
        else puts("hopeless");
    }
    return 0;
}

dfs思路:当发现有个和为正值的环存在时,直接求看该点能否直接到达终点。如果可以,直接返回true,即胜利。否则,继续搜索,当发现所有路径都不能到达终点时,返回false。虽然能ac但不正确。

判断正环的地方 d[u]+e[v]>d[v]
只是点u存在到点v的边,从点u到点v会使点v的值增大,但是点v不一定存在路径能回到点u,这个不一定是一个环。
一组很简单的数据
7
0 2 2 4
-10 1 3
-10 1 6
-10 1 5
30 1 3
-200 1 7

0 0
应该输出失败但是输出了成功
就是在点5到点3过程中,可以使点3的值增大,就判定点5和点3之间有正环,然后从点3找到了到终点7的通路,就判为成功,其实点5和点3之间没有正环,整个图都没有环。

AC代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e3;
#define inf 0x3f3f3f3f
int n,m;
int d[maxn],vis[maxn], energy[maxn];
vector<int >E[maxn];
void init()
{
    for(int i = 0; i < maxn; i++) d[i] = 0, energy[i] = 0;
    for(int i = 0; i < maxn; i++) E[i].clear();
}
int dfs(int u)
{
    if(u == n) return 1;
    vis[u] = 1;
    for(int i  = 0; i < E[u].size(); i++)
    {
        int v = E[u][i];
        if(!vis[v])
        {
            if(dfs(v))
                return 1;
        }

    }
    return 0;
}
int DFS(int u, int e)
{
    if(u == n) return 1;
    d[u]  = energy[u] + e;
    for(int i  = 0; i < E[u].size(); i++)
    {
        int v = E[u][i];
        if(d[u] + energy[v] > 0)
        {
            if(!d[v])
            {
                if(DFS(v, d[u]))
                    return 1;
            }
            else if(d[v] < d[u] + energy[v])
            {
                memset(vis,0,sizeof(vis));
                if(dfs(v))
                    return 1;
            }
        }

    }
    return 0;
}
int main()
{
    int m,k;
    while(~scanf("%d",&n) && n != -1)
    {
         init();
        for(int i = 1; i <= n; i++)
        {
            scanf("%d%d",&energy[i],&m);
            for(int j = 1; j <= m; j++)
            {
                scanf("%d",&k);
                E[i].push_back(k);
            }
        }
        if(DFS(1,100)) puts("winnable");
        else puts("hopeless");
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值