白书数据结构一章中最后一根刺拔掉了!  这题网上大部分都说都是SPFA ,,但是卡了我一个星期dfs 终于给我过掉了

题意:一个有向图,每个节点都有一个值(可能小于0),给定你起始点和初始能量和终点,问你最终在 能量值大于0的情况下能否到达终点

解题思路:dfs,bfs都试过了,最终还是用两个dfs过了,第一个dfs是判断下一个节点是否能走(依赖于第二个dfs)如果能走,如果这个节点在这条路径中走过,如果走过那么判断环的正负,如果是负环就进行第二个dfs判断能否到终点(在途中标记所有的点,如果能走到  则答案为win  如果不能,途中所有的点都不能了)!!

如果这个节点没有走过,那么看到这个节点的之是否大于其他路径到这个节点的值(初始值 = 0  所以不用判断 是否 > 0 的情况) ,如果大于,则继续走下去!

解题代码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int map[105][105];
int limits[105];
int value[105];
int visit[105];
int valuevisit[105];
int vvisit[105];
int canvisit[105];
int n,ok;
void ddfs(int k)
{
   if(ok)
      return;
   if(k == n)
   {
     ok = 1;
     return;
   }
   for(int i = 1;i <= limits[k]; i++ )
   {
      if(!canvisit[map[k][i]])
         {
           canvisit[map[k][i]] = 1;
           ddfs(map[k][i]);
         }
   }

}
void  dfs(int k, int sum)
{
    if(k == n && sum >0 )
    {
      ok = 1;
      return;
    }
    if(ok)
      return;
    for(int i = 1; i <= limits[k]; i ++)
    {
       if(!canvisit[map[k][i]])
        {
           if(visit[map[k][i]])
            {
               if(sum + value[map[k][i]] > valuevisit[map[k][i]])
                 {
                     canvisit[map[k][i]] = 1;
                     ddfs(map[k][i]);
                 }
            }
           else if(sum + value[map[k][i]] > vvisit[map[k][i]])
            {
                 visit[map[k][i]] = 1;
                 valuevisit[map[k][i]] = sum + value[map[k][i]];
                 vvisit[map[k][i]] = sum + value[map[k][i]];
                 dfs(map[k][i],valuevisit[map[k][i]]);
                 valuevisit[map[k][i]] = 0;
                 visit[map[k][i]] = 0;
            }

        }
    }

}
int main()
{

   while(scanf("%d",&n) != EOF)
   {
       if(n == -1)
         break;
       ok = 0;
       memset(map,0,sizeof(map));
       memset(visit,0,sizeof(visit));
       memset(vvisit,0,sizeof(vvisit));
       memset(canvisit,0,sizeof(canvisit));
       memset(value,0,sizeof(value));
      for(int i =1;i <= n;i ++)
      {
         scanf("%d %d",&value[i],&limits[i]);
         for(int j = 1;j  <= limits[i]; j++)
               scanf("%d",&map[i][j]);
      }
      visit[1] = 1;
      valuevisit[1] = 100;
      dfs(1,100);
      if(ok)
        printf("winnable\n");
      else
        printf("hopeless\n");
   }
   return 0;

}
View Code

 

在解题过程中,发现下面的有明显缺陷(在dfs后没有标记掉,判断的环不一定是一个有向环,而且也不是同一路径的环)的代码也能AC, uva的数据还是有点弱啊

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<time.h>
#include<math.h>
#include<limits.h>
struct point
{
    int value;
    int k; 
    int a[103];
}points[105];

int begin,end,ok ,n;
int visit[105];
int vvisit[105];
int isvisit[105];
void dfs1(int p)
{
   //printf("%d\n",p);
    if(p == n)
    {  
        ok = 1;
        return;
    }
    if(ok)
        return ;
    for(int i = 1;i <= points[p].k;i ++)
    {
        if(!isvisit[points[p].a[i]])
        {
            isvisit[points[p].a[i]] = 1;
            dfs1(points[p].a[i]);
        }
    }
    return ;

}
void dfs(int p ,int v)
{
    //printf("%d\n",p);
    if(v <= 0 )
        return;
    if(p == n)
    {  
        ok = 1;
        return;
    }
    if(ok)
        return ;
    for(int i = 1;i <= points[p].k;i ++)
    {
            if(!visit[points[p].a[i]])
            {
                visit[points[p].a[i]] = v + points[points[p].a[i]].value;
                dfs(points[p].a[i],v+points[points[p].a[i]].value);
            }
            else
            {
                    if(v + points[points[p].a[i]].value > visit[points[p].a[i]]  )
                    {
                        isvisit[points[p].a[i]] = 1;
                        dfs1(points[p].a[i]);
                        return;
                    }
            }

    }
    return ;
}
int main(){

    //freopen("/home/plac/problem/input.txt","r",stdin);
    //freopen("/home/plac/problem/output.txt","w",stdout);
    while(scanf("%d",&n) != EOF)
    {
        if(n == -1)
            break;
        begin = 0 ;
        end = 0 ;
        ok = 0 ;
        memset(points,0,sizeof(points));
        memset(visit,0,sizeof(visit));
        memset(vvisit,0,sizeof(vvisit));
        memset(isvisit,0,sizeof(isvisit));
        for(int i = 1; i <= n;i ++)
        {

            scanf("%d %d",&points[i].value,&points[i].k);
            for(int j =1 ;j <= points[i].k;j ++)
            {
                scanf("%d",&points[i].a[j]);
            }
        }
        visit[1] = 100 ;
        dfs(1,100);
        if(!ok)
            printf("hopeless\n");
        else
            printf("winnable\n");
    }
    return 0 ;
}
View Code

 

posted on 2013-06-22 09:53  dark_dream  阅读(188)  评论(0编辑  收藏  举报