JSK习题:成仙之路-(POJ1062)-最短路+限定条件(枚举区间多次最短路)

这里写图片描述

题意:

。。。

思路:

建图时,若物品a能有物品b和c代替,则将b和c连向a,注意要用有向图存。
处理等级限制,枚举最小等级,进行多次最短路计算,求最小值即可。

代码:

#include <iostream>
#include <string.h>
#include <algorithm>
#include <queue>
using namespace std;
const int MAX_N=20500;
struct edge
{
    int to,cost,next;
}e[20*MAX_N];                //要开的足够大
struct node
{
    int cost,level,link_num,id;
    int link[100];
    int link_cost[100];
}nod[20500];              //要开足够大!
int p[MAX_N],eid;
void init()
{
    memset(p,-1,sizeof(p));
    eid=0;
}
void insert(int u,int v,int w)
{
    e[eid].to=v;
    e[eid].cost=w;
    e[eid].next=p[u];
    p[u]=eid++;
}
bool inq[MAX_N];
bool vst[MAX_N];             //用来标记该能能否被选取
int d[MAX_N];
int spfa(int s)
{
    memset(inq,0,sizeof(inq));
    memset(d,0x3f3f,sizeof(d));
    d[s]=0;
    inq[s]=true;
    queue<int>q;
    q.push(s);
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        inq[u]=false;
        for(int i=p[u];i!=-1;i=e[i].next)
        {
            int v=e[i].to;
            if(d[u]+e[i].cost<d[v])
            {
                d[v]=d[u]+e[i].cost;
                if(!inq[v] && !vst[v])       //若该点不能被选取,就不加入队中
                {
                    q.push(v);
                    inq[v]=true;
                }
            }
        }
    }
    return d[1];
}
int main()
{
    int m,n;
    while(cin>>m>>n)
    {
        init();
        for(int i=1;i<=n;i++)
        {
            int p,l,x;
            cin>>p>>l>>x;
            nod[i].id=i;
            nod[i].cost=p;
            nod[i].level=l;
            nod[i].link_num=x;
            for(int j=1;j<=x;j++)
            {
                int t,v;
                cin>>t>>v;
                nod[i].link[j]=t;
                nod[i].link_cost[j]=v;
            }
        }
        int min_level=nod[1].level-m;
        for(int i=1;i<=n;i++)                 //建立有向图
        {
            insert(0,i,nod[i].cost);
            for(int j=1;j<=nod[i].link_num;j++)
            {
                insert(nod[i].link[j],i,nod[i].link_cost[j]);
            }
        }
        int ans=0x3f3f3f3f;
        for(int now_level=min_level;now_level<=nod[1].level;now_level++)     //枚举等级区间
        {
            for(int i=1;i<=n;i++)
            {
                if(nod[i].level<now_level || nod[i].level>now_level+m)       //不能被选取点标记为true
                    vst[i]=true;
                else                                                         //能被选取点标记为false
                    vst[i]=false;
            }
            int res=spfa(0);
            ans=min(res,ans);                   //取多次最短路最小值
        }
        cout<<ans<<endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43093481/article/details/82319089