uva10557 图的杂题

uva10557 图的杂题
    题目链接在此 http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1498。
    这个题是图的一个杂题,想不到什么正统的解法,就乱搞了。昨天做了两个小时无果,基本处在搞不清想法的边缘,然后又不断的涌出新的想法,好吧。题意是说给定一个有向图,每个点有个值,要求从点1走到点N,开始走的时候有初始值。每经过一个点都要加上这个点的值,问能不能在每一步的值都大于0的情况下走到点N。其实最先想到的应该是点1和点N是连通的。然后就是如何处理环的问题。我发现可以在每一个点记录以前到达该点的最大值,如果当前走到这个点的值比最大值小,那么就不需要继续走了,因为上次更大的时候都走不到,现在值变小了也走不到。大概的想法就是这样,总结起来有三点:

1.不走不可联通到末尾借点的点。
2.每次走到点的能量应该更大。
3.有正环,并且这个点可以到达目的地,则成功。
这个题纠结的地方在于DFS判断图联通会超时,我就直接懒的搞写了个floyd-wa什么的动态规划算法判联通性了。
这个题是个不落窠臼的题,我首先想到了环的问题,后来才发现联通问题是更要命的:昨晚写了个BFS直接超时。才发现这个题的判联通和判能量应该分开写。估计数据有比较恶心的稠密图,足以让DFS超时。而我们可以看到,每个点就算访问的最大值不断增加,也最多有2乘100乘100X100的状态(每个节点最多访问2次,节点的最大值也就是所有可能的总和100X100),所以不会超时。而DFS是会死掉地。 #include  < cstdio >
#include <cstring>

int nmap[110][110];

int lstv[110];

int vistime[110];

int reach[110][110];

int eng[110];

int N;

int nfind;

void dfs( int n, int value)
{
   if(nfind == 1)   return;

   if(n == N && value > 0)
  {
    nfind = 1;
     return;
  }

   int i;

   for(i=1;i<=N;i++)
  {
      if(reach[i][N] && nmap[n][i] && lstv[i] < value+eng[i] && value+eng[i] > 0)
     {
       vistime[i]++;
        if(vistime[i] >= 2)
       {
          nfind = 1;
           return;
       }
       lstv[i] = value + eng[i];
       dfs(i,lstv[i]);
       vistime[i]--;
     }
  }
}

int main()
{

   int a,b,c,tmp,i,j,k;
   while(scanf("%d",&N) && N != -1)
  {
      memset(nmap,0, sizeof(nmap));
      memset(reach,0, sizeof(reach));
       for(i=1;i<=N;i++)
      {
         scanf("%d",&eng[i]);
         scanf("%d",&tmp);
          for(j=0;j<tmp;j++)
         {
            scanf("%d",&b);
            nmap[i][b] = reach[i][b] = 1;
         }
      }
       for(i=1;i<=N;i++)
       lstv[i] = -1000000;
    
       for(k=1;k<=N;k++)
        for(i=1;i<=N;i++)
         for(j=1;j<=N;j++)
        {
           if(reach[i][k]>0 && reach[k][j]>0)
            reach[i][j] = 1;
        }
      reach[N][N] = 1;
      memset(vistime,0, sizeof(vistime));
      vistime[1]++;
      nfind = 0;
       if(reach[1][N])
        dfs(1,100);
/*      for(i=1;i<=N;i++)
     {
         for(j=1;j<=N;j++)
        printf("%d ",reach[i][j]);
        printf("\n");
     }
*/
        if(nfind)  printf("winnable\n");  else printf("hopeless\n");
  }
   return 0; 
}

你可能感兴趣的:(uva10557 图的杂题)