POJ 1062 昂贵的聘礼
题意:中文题……
解法:dijkstra。建图建不明白了……绕了好久……最终目标是买1号物品,那么以1为起点,求到所有点的最短路,边权为优惠价格,一条路的最小值为这条路所有边权之和加终点的价格。对于等级的限制条件,每次枚举一个等级区间,只计算区间内点的最短路。
代码:dijkstra又是我自己照流程写的……目测很屎= =但是又懒得找模板……
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string>
#include<string.h>
#include<math.h>
#include<limits.h>
#include<time.h>
#include<stdlib.h>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>
#define LL long long
using namespace std;
struct node
{
int v, val;
node(int v, int val) : v(v), val(val) {}
node() {}
};
vector <node> v[105];
int price[105];
int level[105];
int dis[105];
bool vis[105];
int n, m;
const int inf = 100000000;
void dij(int l)
{
for(int i = 0; i < 105; i++)
{
dis[i] = inf;
vis[i] = 0;
}
if(level[1] < l || level[1] > l + m) return;
dis[1] = 0;
vis[1] = 1;
int len = v[1].size();
for(int i = 0; i < len; i++)
{
int u = v[1][i].v;
if(level[u] < l || level[u] > l + m) continue;
dis[u] = v[1][i].val;
}
while(1)
{
int u = -1, minn = inf;
for(int i = 1; i <= n; i++)
{
if(!vis[i] && (level[i] >= l && level[i] <= l + m))
{
if(dis[i] < minn)
{
minn = dis[i];
u = i;
}
}
}
if(u == -1) break;
vis[u] = 1;
for(int i = 0; i < v[u].size(); i++)
{
int tmp = v[u][i].v;
if(level[tmp] >= l && level[tmp] <= l + m)
{
dis[tmp] = min(dis[tmp], v[u][i].val + dis[u]);
}
}
}
}
int main()
{
while(~scanf("%d%d", &m, &n))
{
for(int i = 0; i < 105; i++)
v[i].clear();
int minn = inf, maxn = 0;
for(int i = 1; i <= n; i++)
{
int num;
scanf("%d%d%d", &price[i], &level[i], &num);
minn = min(level[i], minn);
maxn = max(level[i], maxn);
for(int j = 0; j < num; j++)
{
int a, b;
scanf("%d%d", &a, &b);
v[i].push_back(node(a, b));
}
}
int ans = inf;
minn = max(minn, level[1] - m);
for(int i = minn; i <= maxn; i++)
{
dij(i);
for(int j = 1; j <= n; j++)
ans = min(ans, dis[j] + price[j]);
}
printf("%d\n", ans);
}
return 0;
}

浙公网安备 33010602011771号