POJ 1062 昂贵的聘礼 【最短路】

版权声明:如需转载,记得标识出处 https://blog.csdn.net/godleaf/article/details/88952061

题目链接: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;
 }

猜你喜欢

转载自blog.csdn.net/godleaf/article/details/88952061