poj 1062(Kuangbin最短路专题M题)

/**
输入:输入第一行是两个整数M,N(1 <= N <= 100),依次表示地位等级差距限制和物品的总数。
接下来按照编号从小到大依次给出了N个物品的描述。每个物品的描述开头是三个非负整数P、L、X(X < N),
依次表示该物品的价格、主人的地位等级和替代品总数。
接下来X行每行包括两个整数T和V,分别表示替代品的编号和"优惠后的价格"。

限制条件:所有参与交换的物品主人等级之间差距不超过m 

输出:最少需要的金币数。

解法:构造源点0向每个物品连一条边,dist为物品本身的价格。枚举哪个物品作为等级最高的物品,
限制参与交换的物品(方法为,若某一物品等级超过了等级最高的物品,或者等级过低,把done设成true,
不参与dijkstra的运算)求出最小的金币数。
**/


#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <cmath>
const int inf=1<<27;
const int maxn=105;

using namespace std;

struct Edge
{
    int from,to,dist;
    Edge(int a,int b,int c)
    {
        from=a;
        to=b;
        dist=c;
    }
};

struct node
{
    int status,price;
}s[maxn];

struct HeapNode
{
    int d,u;
    bool operator < (const HeapNode &rhs) const
    {
        return d > rhs.d;
    }
};

struct Dijkstra
{
    int n,m;
    int d[maxn];
    bool done[maxn];
    vector<Edge> edges;
    vector<int> G[maxn];

    void init(int n)
    {
        this->n=n;
        for(int i=0;i<n;i++) G[i].clear();
        edges.clear();
    }

    void add_edge(int from,int to,int dist)
    {
        edges.push_back((Edge){from,to,dist});
        m=edges.size();
        G[from].push_back(m-1);
    }

    void dijkstra(int ss)
    {
        priority_queue<HeapNode> q;
        for(int i=0;i<n;i++) d[i]=inf;
        d[ss]=0;
        q.push((HeapNode){0,ss});

        while(!q.empty())
        {
            HeapNode x=q.top();
            int u=x.u;
            q.pop();
            if(done[u])continue;
            done[u]=true;
            for(int i=0;i<G[u].size();i++)
            {
                Edge &e=edges[G[u][i]];
                if(!done[e.to] && d[e.to]>d[u]+e.dist)
                {
                    d[e.to]=d[u]+e.dist;
                    q.push((HeapNode){d[e.to],e.to});
                }
            }
        }
    }
};

int main()
{
    int m,n,i,x,j,num,cut,maxlv;
    Dijkstra solver;
    scanf("%d%d",&m,&n);
    solver.init(n+1);
    for(i=1;i<=n;i++)
    {
        scanf("%d%d%d",&s[i].price,&s[i].status,&x);
        for(j=0;j<x;j++)
        {
            scanf("%d%d",&num,&cut);
            solver.add_edge(num,i,cut);
        }
        solver.add_edge(0,i,s[i].price);
    }
    int ans=s[1].price;
    for(i=1;i<=n;i++)
    {
        maxlv=s[i].status;
        for(j=1;j<=n;j++)
        {
            if(s[j].status>maxlv || maxlv-s[j].status>m) solver.done[j]=true;
            else solver.done[j]=false;
        }
        solver.done[0]=false;
        solver.dijkstra(0);
        ans=min(ans,solver.d[1]);
    }
    printf("%d\n",ans);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值