《昂贵的礼物》最短路思路详解

题意在这里不再赘述.我想讲的是思路。
首先我们要把这个问题反向来看.把1号人物与其他人物的关系,当成其他人物与他的关系,然后我们建立一个虚拟的人物0,他与所有人的边权都是所有人物的原价值.
转化为图的思想就是,每个人物都是图上的点,然后兑换优惠是边,然后我们反向建边,通过虚拟点出发,不断松弛更新到1的距离,最后这个最短的距离就是我们要的答案。
注意的是:这题还有个等级限制,所以我们枚举以每个人物的等级为下界,他们的等级+m为上界的每个区间,来得到最小的那个答案。

#include<iostream>
#include<stdio.h>
#include<queue>
#include<algorithm>
#include<math.h>
#include<stack>
#include<map>
#include<limits.h>
#include<vector>
#include<string.h>
#include<string>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> pii;
const int N = 3*1e6+5;
const int M = 2*1e5+5;
#define pi acos(-1)
#define INF 1e9
#define INM INT_MIN
#define MAX 205
#define pb(a)  push_back(a)
#define mk(a,b) make_pair(a,b)
#define dbg(x) cout << "now this num is " << x << endl;
#define sd(a) scanf("%d",&a)
#define sld(a) scanf("%lld",&a)
#define sdd(a,b) scanf("%d %d",&a,&b)
#define sddd(a,b,c) scanf("%d %d %d",&a,&b,&c)
#define pr(a) printf("%d\n",a)
#define plr(a) printf("%lld\n",a)
#define pr_(a) printf("%d ",a)
#define _pr(a) printf(" %d",a)
int n,m,cost[105][105],cnt = 1,head[105],dis[105],ans = INF;
struct Node
{
    int price,level,sum;
}p[105];//结构体存信息
struct Edge
{
    int to,next,cost;
}e[10005];
int djst(int ml,int mr)//区间上下界
{
    for(int i=0;i<=n;++i) dis[i] = INF;
    dis[0] = 0;//虚拟点
    priority_queue<pii,vector<pii>,greater<pii> > Q;
    Q.push(pii(0,dis[0]));
    while(!Q.empty())
    {
        int u = Q.top().first,d = Q.top().second;
        Q.pop();
        if(dis[u] < d) continue;
        for(int i=head[u];i;i=e[i].next)
        {
            int y = e[i].to;
            if(p[y].level >= ml && p[y].level <= mr && dis[y] > dis[u]+e[i].cost)
            {
                dis[y] = dis[u]+e[i].cost;
                Q.push(pii(y,dis[y]));
            }
        }
    }
    return dis[1];
}
void add(int u,int v,int w)
{
    e[cnt].to = v;
    e[cnt].cost = w;
    e[cnt].next = head[u];
    head[u] = cnt++;
}
int main()
{
    sdd(m,n);
    for(int i=1;i<=n;++i)
    {
        sddd(p[i].price,p[i].level,p[i].sum);
        int t = p[i].sum;
        while(t--)
        {
            int x,z;
            sdd(x,z);
            add(x,i,z);//反向建边
        }
        add(0,i,p[i].price);//虚拟点到所有人的距离就是他们自己的价格
    }
    for(int i=1;i<=n;++i)//不断枚举区间更新
    {
        int ml = p[i].level;//划定下界
        ans = min(ans,djst(ml,ml+m));
    }
    pr(ans);
}
发布了14 篇原创文章 · 获赞 0 · 访问量 2942

猜你喜欢

转载自blog.csdn.net/weixin_45671214/article/details/104352926
今日推荐