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

来源:互联网 发布:文档网络在哪里 编辑:程序博客网 时间:2024/06/04 20:38

题目链接:[POJ 1062]昂贵的聘礼[最短路][枚举]
题意分析:
中文题。注意这句话:

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

也就是说:同一条路径上的任意两个人,等级差不能超过M。
解题思路:
另设一个源点0,让源点0和所有人连边,权值就是物品的原价。
可以兑换的物品间连一条线,权值为优惠后价格。
这样问题就转换成了,从0到1的最短路是多少?
由于每条路径需要满足任意两个人等级差不超过M,所以我们枚举道路上的最小等级,然后每次求一次最短路即可。
个人感受:
被中文题卡题意了= =。细看那句话好像也对,没啥子歧义= =。可怕。
具体代码如下:

#include<cstdio>#include<cstring>#include<iostream>#define ll long longusing 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;}
0 0