POJ-1062 昂贵的聘礼 区间枚举

第二次来做这一题,由于题目中给定了一个等级限制M,所以可以通过枚举第一个点所在的位置求解.思路很清晰.

for (int i = 0; i <= M; ++i) 这个i来表示第一个点的等级在M长度区间内的偏移量.然后再在区间内建边,floyd即可.

代码如下:

#include <cstdlib>

#include <cstdio>

#include <cstring>

#include <algorithm>

#include <iostream>

#define INF 0x3f3f3f3f

using namespace std;



int M, N, mey[105], lvl[105], head[105], idx;



int lwall, rwall, G[105][105];



struct Edge {

    int v, val, next;

}e[10005]; // 保留替换列表 



void addedge(int x, int v, int val) {

    ++idx;

    e[idx].v = v, e[idx].val = val;

    e[idx].next = head[x], head[x] = idx;

}



inline bool in(int x) {

    if (lvl[x] >= lwall && lvl[x] <= rwall) {

        return true;    

    } else return false;

}



void build() {

    memset(G, 0x3f, sizeof (G));

    for (int i = 1; i <= N; ++i) {

        G[i][i] = 0;

        for (int j = head[i]; j != -1; j = e[j].next) {

            if (in(i) && in(e[j].v)) {

                G[i][e[j].v] = e[j].val;

            }

        }    

    }

}



void floyd(int &ret) {

    for (int k = 1; k <= N; ++k) {

        for (int i = 1; i <= N; ++i) {

            for (int j = 1; j <= N; ++j) {

                if (G[i][k]!=-1&&G[k][j]!=-1) { // 有边相连 

                    G[i][j] = min(G[i][j], G[i][k]+G[k][j]);

                }

            }    

        }    

    }

    for (int i = 1; i <= N; ++i) {

        if (G[1][i] != INF) {

            ret = min(ret, G[1][i]+mey[i]);

        }

    }

}



int main() {

    int c, v, val, ret;

    while (scanf("%d %d", &M, &N) == 2) {

        ret = INF;

        idx = -1;

        memset(head, 0xff, sizeof (head));

        for (int i = 1; i <= N; ++i) {

            scanf("%d %d %d", &mey[i], &lvl[i], &c);

            for (int j = 1; j <= c; ++j) {

                scanf("%d %d", &v, &val);

                addedge(i, v, val);

            }

        }

        // 通过枚举第一个点在M区间的最左边和最右边 

        for (int i = 0; i <= M; ++i) {

            lwall = lvl[1]-i, rwall = lwall+M;

            if (lwall < 0) break; // 左边界不可能为负数 

            // 确定好了左右界在进行构边

            build();

            floyd(ret);

        }

        printf("%d\n", ret);

    }

    return 0;    

}

 

你可能感兴趣的:(poj)