其他分享
首页 > 其他分享> > 题解【POJ1062】昂贵的聘礼

题解【POJ1062】昂贵的聘礼

作者:互联网

题面

比较复杂的最短路模型转换。

我们考虑一种建图方式:

考虑等级限制,我们可以枚举当前最低的等级,然后在进行松弛操作的时候判断一下当前节点是否在当前等级限制之内。每一次跑完最短路后将答案与当前的 \(dist_1\) 取 \(\text{min}\)。

注意从 \(0\) 开始枚举最低等级。

#include <iostream>
#include <cstring>
#include <queue>

using namespace std;

const int N = 103, M = 20003;

int n, m;
int grade[N]; //每个物品的等级
int tot, head[N], ver[M], nxt[M], edge[M];
int dist[N], vis[N];
int S;

inline void add(int u, int v, int w)
{
    ver[++tot] = v, edge[tot] = w, nxt[tot] = head[u], head[u] = tot;
}

inline void Dij(int s/*起点*/, int t/*终点*/, int LowGrade/*当前的最低等级*/, int HighGrade/*当前的最高等级*/)
{
    memset(dist, 0x3f, sizeof dist);
    priority_queue <pair <int, int> > q;
    dist[S] = 0;
    memset(vis, 0, sizeof vis);
    q.push(make_pair(0, S));
    while (!q.empty())
    {
        int u = q.top().second; q.pop();
        vis[u] = 0;
        for (int i = head[u]; i; i = nxt[i])
        {
            int v = ver[i], w = edge[i];
            if (grade[v] < LowGrade || grade[v] > HighGrade) continue; //不满足当前的等级限制
            if (dist[v] > dist[u] + w)
            {
                dist[v] = dist[u] + w;
                if (!vis[v])
                    vis[v] = 1,
                    q.push(make_pair(-dist[v], v));
            }
        }
    }
}

int main()
{
    cin >> m >> n;
    S = n + 1; //超级源点
    for (int i = 1; i <= n; i+=1)
    {
        int u = i, v, w, x;
        cin >> w >> grade[i] >> x;
        add(S, u, w); //向超级源点连一条权值为物品价格的边
        for (int j = 1; j <= x; j+=1)
            cin >> v >> w,
            add(v, u, w); //由替代品向当前物品连边
    }
    int ans = 2000000007;
    for (int nowLowGrade = 0; nowLowGrade <= n; nowLowGrade+=1) //枚举最低等级,注意要从 0 开始
    {
        Dij(S, 1, nowLowGrade, nowLowGrade + m); //跑一次 Dijkstra 最短路
        ans = min(ans, dist[1]); //将答案取最小值
    }
    cout << ans << endl;
    return 0;
}

标签:POJ1062,dist,当前,int,题解,tot,vis,聘礼,等级
来源: https://www.cnblogs.com/xsl19/p/12376535.html