题意:
。。。
思路:
建图时,若物品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;
}