这道题题目理解不难,可以转化为求最短路径。
最开始的话,我直接就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;
}