您的位置:首页 > 其它

[POJ 1062]昂贵的聘礼[最短路][枚举]

2015-10-24 00:38 330 查看
题目链接:[POJ 1062]昂贵的聘礼[最短路][枚举]

题意分析:

中文题。注意这句话:

地位差距超过一定限制的两个人之间不会进行任何形式的直接接触,包括交易。他是一个外来人,所以可以不受这些限制。但是如果他和某个地位较低的人进行了交易,地位较高的的人不会再和他交易,他们认为这样等于是间接接触,反过来也一样。

也就是说:同一条路径上的任意两个人,等级差不能超过M。

解题思路:

另设一个源点0,让源点0和所有人连边,权值就是物品的原价。

可以兑换的物品间连一条线,权值为优惠后价格。

这样问题就转换成了,从0到1的最短路是多少?

由于每条路径需要满足任意两个人等级差不超过M,所以我们枚举道路上的最小等级,然后每次求一次最短路即可。

个人感受:

被中文题卡题意了= =。细看那句话好像也对,没啥子歧义= =。可怕。

具体代码如下:

#include<cstdio>
#include<cstring>
#include<iostream>
#define ll long long
using namespace std;

const int INF = 0x7f7f7f7f;
const int MAXN = 111;

struct Edge{
int to;
int next;
ll w;
}edge[MAXN * MAXN];
ll p, rnk[MAXN], dis[MAXN], m;
int head[MAXN], sta[MAXN], cnt = 0;
bool in[MAXN];

void add_edge(int from, int to, ll w)
{
edge[cnt].w = w;
edge[cnt].to = to;
edge[cnt].next = head[from];
head[from] = cnt++;
}

ll spfa(int s, ll rk) // rk:最小等级
{
memset(dis, 0x7f, sizeof dis);
dis[s] = 0;
int top = 0;
sta[top++] = s; // 栈模拟spfa
in[s] = 1;
while (top)
{
int cur = sta[--top]; in[cur] = 0;
for (int i = head[cur]; ~i; i = edge[i].next)
{
Edge &e = edge[i];
if (rnk[e.to] > rk + m || rnk[e.to] < rk) continue; // 不符合等级要求
if (dis[e.to] > dis[cur] + e.w)
{
dis[e.to] = dis[cur] + e.w;
if (!in[e.to])
{
sta[top++] = e.to;
in[e.to] = 1;
}
}
}
}
return dis[1];
}

int main()
{
int n, x, from;
ll w;
scanf("%lld %d", &m, &n);
memset(head, -1, sizeof head);
for (int i = 1; i <= n; ++i)
{
scanf("%lld %lld %d", &p, &rnk[i], &x);
add_edge(0, i, p);
while (x --)
{
scanf("%d %lld", &from, &w);
add_edge(from, i, w);
}
}

ll mind = INF;
for (int i = 1; i <= n; ++i)
mind = min(spfa(0, rnk[i]), mind);

printf("%lld\n", mind);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: