POJ 1602 昂贵的聘礼(区间枚举 + dij堆优化)

POJ 1602 昂贵的聘礼(区间枚举 + dij堆优化)

vj链接

Solution

一开始以为是相邻的两个人等级不能超过m。。wa了好多发

观察到点的总数不超过 100,那么只要区间 [ l e v e l [ 1 ] − m , l e v e l [ 1 ] ] [level[1]-m,level[1]] [level[1]m,level[1]] 为下界,每次跑一遍 dij 即可,最多跑 m 次,如果使用离散化处理的话可以优化到最多跑 100 次 (数据水了所以代码里没用)

代码

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<vector>
#include<map>
#include<cmath>
#include<string>
#include<queue>
#include<set>
#define int long long
using namespace std;
typedef pair<int, int> pii;
typedef pair<double, int> pdi;
typedef double dd;
typedef long long ll;
const int MAXN = 210;
const int MAXM = 100010;
const dd eps = 1e-6;
const int inf = 0x3f3f3f3f;

struct NODE{
    int id, w, lv;
    bool operator<(const NODE &a)const{
        return lv < a.lv;
    }
} nd[MAXN];
int idd[MAXN];
int e[MAXN][MAXN];
bool vis[MAXN];
int dis[MAXN];
int m, n;

ll minn(ll a,ll b){
    if(a>b)
        return b;
    return a;
}

void dij(int p,int d, int s)
{
    // for (int i = 1; i <= n;i++)
    //     dis[i] = nd[i].w;
    memset(vis, 0, sizeof(vis));
    memset(dis, 0x3f, sizeof(dis));
    priority_queue<pii, vector<pii>, greater<pii>> q;
    dis[s] = 0;
    q.push(pii(dis[s], s));
    while(q.size())
    {
        int u = q.top().second;
        q.pop();
        if(vis[u])
            continue;
        vis[u] = 1;
        for (int i = 1; i <= n;i++)
        {
            int w = e[u][i];
            if(nd[i].lv <= p && nd[i].lv >= d && dis[i] > dis[u] + w)
            {
                dis[i] = dis[u] + w;
                q.push(pii(dis[i], i));
            }
        }
    }
}

signed main()
{
    memset(e, 0x3f, sizeof(e));
    cin >> m >> n;
    for (int i = 1; i <= n;i++)
    {
        int p, l, x;
        cin >> p >> l >> x;
        nd[i].id = i, nd[i].w = p, nd[i].lv = l;
        e[0][i] = p;
        while(x--)
        {
            int t, v;
            cin >> t >> v;
            e[t][i] = v;
        }
    }
    int ans = inf;
    for (int i = minn(0ll, nd[1].lv - m); i <= nd[1].lv; i++)
    {
        dij(i + m, i, 0);
        ans = minn(ans, dis[1]);
    }
    printf("%lld", ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值