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

传送门
// 中文就不多说题意了.

思路: 我们首先明确一点的就是我们的关键人物是1号点, 因为我们我们找出的一条路径上所有人的等级都是跟1号点有着联系的, 所以我们直接枚举该范围, 我们通过对题意的了解知道对于一个物品它的优惠物品到它应该有条单向边, 但是我们由于后面计算的了解知道我们每枚举一次范围就会算所有点到1点的最短距离, 即多源单汇的情况, 所有我们先建图的时候反向建图, 然后以1作为起点跑最短路取最小即可. 还有就是等级范围, 假设1号点等级为d[1], 等级差为m , 那么我们要枚举的范围就是(d[1] - m, d[1]), (d[1] - m + 1, d[1] + 1), …., (d[1] - m + m, d[1] + m). 假设d[1] =4, m = 2, 那么范围就是(2, 4), (3, 5), (4, 6). 不在这个范围内的就是不能要的点, 然后取其中最小的即可.

AC Code

const int maxn = 1e2+5;
int cas=1;
int n, m;
int a[maxn], d[maxn];
struct node {
    int to, next, w;
    node() {to = next = w = 0;}
    node(int to, int next, int w):
        to(to), next(next), w(w) {}
    bool operator < (const node& a) const {
        return w > a.w;
    }
} e[maxn*maxn];

int cnt , head[maxn];
void add(int u, int v, int w) {
    e[cnt] = node(v, head[u], w);
    head[u] = cnt++;
}
void init() {
    cnt = 0;
    Fill(head, -1);
}
int dis[maxn];
bool vis[maxn];
int dij(int st, int down, int up) {
    priority_queueq;
    Fill(dis, inf); Fill(vis, false);
    dis[st] = 0; q.push(node(st, 0, 0));
    while(!q.empty()) {
        node u = q.top();
        q.pop();
        if (vis[u.to]) continue;
        vis[u.to] = 1;

        for (int i = head[u.to] ; ~i ; i = e[i].next) {
            int to = e[i].to;
            if (d[to] < down || d[to] > up) continue;
            if(dis[to] > dis[u.to] + e[i].w) {
                dis[to] = dis[u.to] + e[i].w;
                q.push(node(to, 0, dis[to]));
            }
        }
    }
    int ans = inf;
    for (int i = 1 ; i <= n ; i ++) {
        ans = min(ans, dis[i] + a[i]);
    }
    return ans;
}
void solve()
{
    while(~scanf("%d%d", &m, &n)) {
        init();
        for (int i = 1 ; i <= n ; i ++) {
            int x;
            scanf("%d%d%d", &a[i], &d[i], &x);
            while(x--) {
                int st, w;
                scanf("%d%d", &st, &w);
                add(i, st, w);
            }
        }
        int ans = inf;
        for (int i = 0 ; i <= m ; i ++) {
            int tmp = dij(1, d[1] - m + i, d[1] + i);
            ans = min(ans, tmp);
        }
        printf("%d\n", ans);
    }
}

你可能感兴趣的:(最短路相关)