POJ1062 昂贵的聘礼(最短路)

题目链接

分析:

一开始以为简单的DFS,直接做,MLE了。

本体应该用最短路径(Dijkstra算法)做。

此题的关键在于等级限制的处理,采用枚举,即假设酋长等级为5,等级限制为2,那么需要枚举等级从3~5,4~6,5~7
从满足改等级范围的结点组成的子图中用Dijkstra来算出最短路径,最后求出最小值。

AC代码如下:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <queue>

using namespace std;

const int maxn = 100+10;
const int INF = (1<<29);

int G[maxn][maxn], level[maxn], val[maxn], n, d[maxn];
bool lim[maxn];

int dijkstra() {
    bool vis[maxn];
    memset(vis, false, sizeof(vis));

    for(int i=1; i<=n; i++) d[i] = INF;
    d[1] = 0;

    for(int i=1; i<n; i++) {
        int m = INF, x;
        for(int y=1; y<=n; y++) if(!vis[y] && lim[y] && m >= d[y]) m = d[x=y];
        vis[x] = true;
        for(int y=1; y<=n; y++) if(!vis[y] && lim[y] && d[y]>d[x]+G[x][y]) d[y] = d[x]+G[x][y];
    }

    int ans = INF;
    for(int i=1; i<=n; i++) {
        d[i] += val[i];
        ans = min(ans, d[i]);
    }
    return ans;
}

int main() {
    int p, l, x, t, v;
    int m;
    //freopen("my.txt", "r", stdin);
    while(scanf("%d%d", &m,&n) == 2) {
        for(int i=1; i<=n; i++) {
            for(int j=1; j<=n; j++) {
                G[i][j] = INF;
            }
        }

        for(int i=1; i<=n; i++) {
            scanf("%d%d%d", &p, &l, &x);
            val[i] = p; level[i] = l;

            for(int j=0; j<x; j++) {
                scanf("%d%d", &t, &v);
                G[i][t] = v;
            }
        }

        int ans = INF;

        for(int i=0; i<=m; i++) {
            memset(lim, false, sizeof(lim));
            for(int j=1; j<=n; j++) {
                if(level[j] >= level[1]-m+i && level[j] <= level[1]+i) lim[j] = true;
            }

            ans = min(ans, dijkstra());
        }

        printf("%d
", ans);
    }

    return 0;
}
View Code

MLE代码也贴下。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <queue>

using namespace std;

const int maxn = 100+10;

struct Edge {
    int nu, p, next;
}ed[1000000];

struct node {
    int p, l;
    int next;
}head[maxn];

int mem, m;

void add(int u, int v, int p) {
    ed[mem].nu = v;
    ed[mem].p = p;
    ed[mem].next = head[u].next;
    head[u].next = mem++;   
};

int dfs(int u, int minv, int maxv) {

    int ans = head[u].p;

    for(int i=head[u].next; i != -1; i = ed[i].next) {
        int nmin = min(minv, head[ed[i].nu].l);
        int nmax = max(maxv, head[ed[i].nu].l);
        if(nmax - nmin > m) continue;
        if(ed[i].p >= ans) continue;
        ans = min(ans, ed[i].p + dfs(ed[i].nu, nmin, nmax));
    }

    return ans;
}

int main() {
    int n;
    int p, l, x, nu;

    //freopen("my.txt", "r", stdin);
    while(scanf("%d%d", &m,&n) == 2) {
        mem = 0;

        for(int i=1; i<=n; i++) {
            scanf("%d%d%d", &p, &l, &x);

            head[i].p = p; head[i].l = l; head[i].next = -1;

            for(int j=0; j<x; j++) {
                scanf("%d%d", &nu, &p);
                add(i, nu, p);
            }
        }

        printf("%d
", dfs(1, head[1].l, head[1].l));
    }

    return 0;
}
View Code
原文地址:https://www.cnblogs.com/tanhehe/p/3158535.html