POJ 1602 昂贵的聘礼(区间枚举 + dij堆优化)
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);
}