POJ 1062 有限制条件的最短路

见到得POJ第一道中文题。

刚开始算法想错了,交上去果断WA

刚开始错误得算法:

1. 根据题意建好图

2.floyd求传递闭包。

3.以1为起点,求一次Dijsktra算法,并记录其路径

4.枚举1可以到的点,求出其最小直,并判断该路径上得点是否满足等级限制

交上去错了后,才发现算法错了。。

1 4
10000 3 2
2 1
3 3
1000 2 2
4 1
3 1
1000 3 1
4 2
100 4 0

这组数据就能完全否认我的算法。并且改不过来。果断换算法。
看了discuss,有人说,枚举等级限制,求多次Dijkstra,很暴力,但毫无疑问时正确的算法。
正确算法如下:
1.建好图
2.枚举等级,如果酋长等级是4,限制为2,那么等级区间为2-4,3-5,4-6
3.求最短路

写好后,又Wa了,dis[v] > dis[k] + w 没有加dis[k] != inf 悲剧。
View Code
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <algorithm>
using namespace std;

#define MAXN 501000
struct Edge
{
  int u, next, val;
  Edge() { }
  Edge( int U, int Next, int Val): u(U), next(Next), val(Val) { }
}edge[MAXN];

const int inf = 0x7f7f7f7f;
int M, N, head[MAXN], dis[MAXN], visit[MAXN], size;
int rank[110]; //该点等级
int price[110]; //该点价格
int limit[110];//等级限制
int out[110]; //该点的出度,也就是替代品总数




void init( )
{
  for( int i = 0; i <= N; i++)
  {
      head[i] = -1;
      price[i] = 0;
      rank[i] = 0;
      out[i] = 0;
  }
  size = 0;

}

void AddEdge( int u, int v, int val)
{
   edge[size] = Edge(v, head[u], val);
   head[u] = size++;

}


//求最短路Dijsktra算法
int dij( )
{ 
  for( int i = 1; i <= N; i++)
  {
     dis[i] = inf;
     visit[i] = 0;
  }
  dis[1] = 0;
  for( int i = 1; i <= N; i++)
  {
      int oo = inf, k = 0;
      for( int j = 1; j <= N; j++)
      {
         if( !visit[j] && dis[j] < oo && limit[j])
         {
             oo = dis[j];
             k = j;

         }

      }
      visit[k] = 1;
      for( int e = head[k]; e != -1; e = edge[e].next )
      {
         int v = edge[e].u;
         int w = edge[e].val;
         if(!visit[v] && dis[v] > dis[k] + w && limit[v] && dis[k] != inf)
         {
              dis[v] = dis[k] + w;
         }

      }

  }
  int oo = inf;
  for( int i = 1; i <= N; i++)
  {
      dis[i] += price[i];
      if( oo > dis[i] )
    oo = dis[i];

  }
  return oo;
}


int main( )
{
  int a, b;
  scanf("%d%d", &M, &N);
  
     init( );
     for( int i = 1; i <= N; i++)
     {
         scanf("%d%d%d", &price[i], &rank[i],&out[i]);  
         for( int j = 1; j <= out[i]; j++)
         {
              scanf("%d%d",&a, &b);
              AddEdge( i, a, b);
         } 

     }
     int ans = rank[1], minxx = inf;
     for( int i = 0; i <= M; i++)
     {
         memset(limit, 0, sizeof(limit));
         for( int j = 1; j <= N; j++)
           if( rank[j] >= ans - M + i && rank[j] <= ans + i )
               limit[j] = 1; 
         int minx = dij( );
         minxx = min( minx, minxx);

     }
     printf("%d\n",minxx);

   
  return 0;
}

posted on 2012-07-11 19:05  more think, more gains  阅读(260)  评论(0编辑  收藏  举报

导航