UVa OJ 10557

1、这题真心把我坑死了,昨天下午两点开始做的,次日凌晨五点才AC(当然中途有休息),uva数据就是BT。。。

2、刚开始反复RE,终于明白RE不止是数组越界还可能有栈溢出的原因。据说用STL的队列就显示TLE,如果用普通数组模拟就是RE。长知识了。

3、后来反复WA,非常邪门,把bfs改成dfs,再把dfs改成bfs,还是不行,最后只能上网搜解题报告了。

4、递归的部分和解题报告已经是一样的了,居然还是WA,到底是怎么回事?最后想啊想啊终于想到了,原来是“判断是否能到达终点”的时候,应该从“当前结点”开始搜索,而不是从“结点1”开始搜索,因为这是有,向,图!!!我本来以为从“当前结点”肯定能回到“结点1”,太天真了!!!

5、每次都犯这种非常低级的错误= =。。。

6、简单说下思路吧,就是判断是否存在一条从起点到终点的通路,使得边权相加为正,且中途不能有边权和为非正(负数或0)的时候,但由于图可能含有环(正环或负环),所以要加特判。怎么判断有正环呢?只要看再次访问结点的时候,当前权值之和是否大于历史权值之和,如果是,则说明是正环,要判断从“当前结点”是否能到终点(我就是栽在这里)。

7、还有一个要注意的就是每次访问一个新的结点的时候,必须要先判断权值和是否为负,因为如果权值和已经为负,这条路肯定不通了(题目要求,因为血掉光了嘛),所以负环根本不用担心,只要加了这一条if语句,就可以避免死循环了。(我开始就是因为没加这个,从bfs改成dfs再改成bfs,怎么都是死循环,这也是个教训了。)

8、用邻接表保存结点比较方便。

9、还有注意一些计数的变量如i,j不要用全局变量,函数一多很容易搞混。

10、有大神说用SPFA可以做。。。但我不会(囧),感觉自己真是弱爆了。。。

#include<cstdio>
#include<cstring>
int n,t;
int a[110][110],val[110],c[110],e[110],q[110];
bool judge,flag;
void init(void)
{
    int i,j;
    for(i=1;i<=n;i++)
    {
        scanf("%d%d",&val[i],&a[i][0]);
        for(j=1;j<=a[i][0];j++)
        {
            scanf("%d",&a[i][j]);
        }
    }
    return;
}
bool have_exit(int num)
{
    int v,i,front=0,rear=0;
    c[num]=1;q[rear++]=num;
    while(front<rear)
    {
         v=q[front++];
         for(i=1;i<=a[v][0];i++)
         {
             if(!c[a[v][i]])
             {
                 if(a[v][i]==n)return true;
                 q[rear++]=a[v][i];
                 c[q[rear-1]]=1;
             }
         }
    }
    return false;
}
bool dfs(int num,int energy)
{
    int u,i;
    if(num==n&&energy>0) return true;
 for(i=1;i<=a[num][0];i++)
 {
      u=a[num][i];
   if(energy+val[u]>0)
   {
    if(!e[u])
    {
     e[u]=energy+val[u];
     if(dfs(u,e[u])) return true;
    }
    else if(e[u]<energy+val[u]&&have_exit(u))
            {
                   return true;
            }
   }
    }
    return false;
}
void print(void)
{
    if(dfs(1,100))
       printf("winnable\n");
    else
       printf("hopeless\n");
}
int main(void)
{
    //freopen("a.txt","r",stdin);
    while(scanf("%d",&n)==1)
    {
        if(n==-1)break;
        memset(a,0,sizeof(a));
        memset(val,0,sizeof(val));
        memset(c,0,sizeof(c));
        memset(e,0,sizeof(e));
        memset(q,0,sizeof(q));
        init();
        e[1]=100;
        print();
     }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值