poj 1062 dijisktra+枚举

这道题题目理解不难,可以转化为求最短路径。

最开始的话,我直接就dijisktra,然后对于每条可以到达酋长的路径检查是否满足等级限制,然后选最小的

但是WA,原因是如果某条路径等级出现大于M的情况,那么这条路径先前的某些点需要退回去修改被改过的节点值,也就是得用dfs写。

后来搜了一下网上的解法,竟然用枚举!!!枚举出等级差小于M区间,对满足区间的点进行dijisktra,然后取最小,我开始时没有想到。。。。。。。。。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAX 99999
#define MAX_SIZE_OF_VEXS 110

typedef struct
{
        int vexs[MAX_SIZE_OF_VEXS];
        int arcs[MAX_SIZE_OF_VEXS][MAX_SIZE_OF_VEXS];
        int vex_num;
        int arc_num;
}graph;

int main()
{
    int M,N;
    graph *g;
    int dist[MAX_SIZE_OF_VEXS];
    bool final[MAX_SIZE_OF_VEXS];
    int pre[MAX_SIZE_OF_VEXS];
    int level[MAX_SIZE_OF_VEXS];
    int count[MAX_SIZE_OF_VEXS];
    int is_in[MAX_SIZE_OF_VEXS];
    int first,last;
    int min_dis = MAX,dis;
    int loc,temp;

     while (scanf("%d%d",&M,&N) != EOF)
     {
           min_dis = MAX;
           g = (graph*)malloc(sizeof(graph));
           g->vex_num = N+1;
           for(int i = 0;i <= N; i++)
                for(int j = 0;j <= N; j++)
                     g->arcs[i][j] = (i == j)?0:MAX;
           for(int i = 1;i <= N; i++)
           {
                   scanf("%d%d%d",&dist[i],&level[i],&count[i]);
                   g->arcs[0][i] = dist[i];
                   for(int j = 1;j <= count[i];j++)
                   {
                       scanf("%d",&temp);
                       scanf("%d",&(g->arcs[temp][i]));
                   } 
           }
           
           for(first = level[1]-M;first <= level[1]; first++)
           {
                   last = first+M;
                   memset(is_in,0,sizeof(is_in));
                   is_in[0] = 1;
                   is_in[1] = 1;
                   for(int i = 2;i <= g->vex_num-1; i++)
                      if(level[i] >= first && level[i] <= last)  
                          is_in[i] = 1;
                      //dijskra
     for(int i = 0;i < g->vex_num; i++)
     {
             final[i] = false;
             dist[i] = g->arcs[0][i];
             pre[i] = 0;
     }
     final[0] = true;
     for(int q = 1;q <= g->vex_num-1; q++)
     {
             int min = MAX,k;
             for(int j = 0;j <= g->vex_num - 1;j++)
             {
                 if(is_in[j] && !final[j] && min > dist[j])
                 {
                        k = j;
                        min = dist[j];
                 }
             }
         
             final[k] = true;
         
             for(int j = 0; j <= g->vex_num-1; j++)
             {
                  if(is_in[j] && !final[j] && dist[j] > dist[k]+g->arcs[k][j])
                  {
                               dist[j] = dist[k]+g->arcs[k][j];
                               pre[j] = k;
                  }   
             }
     }//end for dijsktra
     loc = 1;
     dis = 0;
     while(1)
     {
               dis += g->arcs[pre[loc]][loc];
               if(pre[loc] == 0)  break;
               loc = pre[loc];
     }
  
     if(dis < min_dis)  min_dis = dis;
                }
     printf("%d\n",min_dis);
     }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值