说白了就是给你一张图,每个点有一个等级限制,在等级限制以内求一条最短路。
构图方法:首先将原点0连向每一个物品对应的编号,那么边权为物品的初始价格;如果对于物品j,如果有了物品i,那么j的优惠价为w,就在i,j之间连一条权值为w的边。最后枚举等级的范围(注意等级的上下差为m,其中包含了酋长的等级,而不是与酋长等级差的绝对值小于等于m QAQ),求到原点到酋长(0号点到1号点)的最短路。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
struct T
{
int v;
int w;
int next;
}edge[10010];
int head[110],cnt;
void add_edge(int u,int v,int w)
{
edge[cnt].v = v;
edge[cnt].w = w;
edge[cnt].next = head[u];
head[u] = cnt++;
}
int m,n;
int abs(int x)
{
return x>0?x:-x;
}
int dis[110];
int lv[110];
bool vis[110];
void BFS(int dn,int up)//求最短路
{
memset(dis,0x3f,sizeof dis);
memset(vis,0,sizeof vis);
queue<int> myque;
dis[0] = 0;
vis[0] = 1;
myque.push(0);
while(!myque.empty())
{
int u = myque.front();
myque.pop();
for(int i = head[u]; i != -1; i = edge[i].next)
{
int v = edge[i].v;
int w = edge[i].w;
if(!vis[v]&&lv[v] >= dn&&lv[v] <= up)
{
if(dis[u] + w < dis[v])
dis[v] = dis[u] + w;
myque.push(v);
vis[v] = 1;
}
else if(dis[u] + w < dis[v]&&lv[v] >= dn&&lv[v] <= up)
dis[v] = dis[u] + w;
}
}
}
int main()
{
memset(head,-1,sizeof head);
int p,x;
int y,z;
scanf("%d%d",&m,&n);
for(int i = 1; i<= n; i++)
{
scanf("%d%d%d",&p,&lv[i],&x);
add_edge(0,i,p);
add_edge(i,0,p);
for(int j = 1; j <= x; j++)
{
scanf("%d%d",&y,&z);
add_edge(y,i,z);
add_edge(i,y,z);
}
}
int ans = 123456789;
for(int i = lv[1]-m; i <= lv[1]; i++)//枚举等级范围
{
BFS(i,i+m);
if(dis[1] < ans)
ans = dis[1];
}
printf("%d\n",ans);
}