题目链接:http://poj.org/problem?id=1062
假设一个起点0,根据题目给出的权值构图,答案就是从0到1之间的最短路。
这里要注意的是这个等级限制的问题。
首先等级限制不是相邻点之间的限制,而是整体路径的。
等级的限制可以通过假设一个点为最低点求最短路,我假设某个点是最短路中等级最低的,然后求最短路。每枚举一个点就求一次最短路,取最小的值。
因为你枚举的点已经是等级最低的了,所以不能有比自己还低的,而且比自己高的不能超过M。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <cmath>
using namespace std;
const int Maxn = 210+10;
const int INF = 0x3f3f3f3f;
const double esp = 1e-6;
struct Edge {
int v, w, next;
} edge[Maxn*Maxn];
int d[Maxn], head[Maxn], edge_cnt, Rank[Maxn];
bool vis[Maxn];
void add (int u, int v, int w) {
edge[edge_cnt].v = v;
edge[edge_cnt].w = w;
edge[edge_cnt].next = head[u];
head[u] = edge_cnt++;
}
int dij(int x, int n, int k) {
memset(vis, false, sizeof(vis));
memset(d, INF, sizeof(d));
d[0] = 0;
while(1) {
int u = -1;
for(int i = 0; i <= n; ++i) if(!vis[i] && (u == -1 || d[u] > d[i])) u = i;
if(u == -1) break;
vis[u] = true;
if((Rank[u] < Rank[x] || Rank[x]+k < Rank[u])) continue;
for(int i = head[u]; i != -1; i = edge[i].next) {
Edge &e = edge[i];
if((Rank[e.v] < Rank[x] || Rank[x]+k < Rank[e.v])) continue;
if(!vis[e.v] && d[e.v] > d[u]+e.w) {
d[e.v] = d[u]+e.w;
}
}
}
return d[1];
}
int main(void)
{
int k, n, m;
scanf("%d%d", &k, &n);
memset(head, -1, sizeof(head));
edge_cnt = 0;
for(int i = 1; i <= n; ++i) {
scanf("%d%d%d", &d[i], &Rank[i], &m);
int v, w;
add(0, i, d[i]);
while(m--) {
scanf("%d%d", &v, &w);
add(v, i, w);
}
}
int ans = INF;
for(int i = 1; i <= n; ++i) {
Rank[0] = Rank[i];
ans = min(ans, dij(i, n, k));
}
printf("%d\n", ans);
return 0;
}