/**
题意:一个人它需要获得一件物品,但是呢他现在的钱不是很够,
所以呢它可以进行周转得到更多的金币,那么它应该怎么做呢?
所谓周转就是用金币换 或者以物换物,因为同一件商品在不同的人里面
它的价值可能是不一样的,所以它需要通过花最少的钱来获得该物品
所需的费用;(因为它开始买东西也是需要费用的);
这个题目呢主要卡的就是你的等级限制;
所以呢咋们就需要找到它的所有的等级,因为它会存在重复的情况;
以每一个不重复等级进行SPFA找在等级差距的范围内的最小值,
因为我们每一次的花费都不一定是最小,所以我们需要存储中间最优解;
然后进行不断更新,取最小值就好了;
*/
#include<iostream>
#include<cstdio>
#include<cmath>
#include<queue>
#include<stack>
#include<cstring>
#include<algorithm>
using namespace std;
int MIN(int a,int b) {return (a>b)?b:a;}
int MAX(int a,int b) {return (a>b)?a:b;}
const int INF=0x3f3f3f3f;
const int maxm=1e5+7;
const int maxn=1e2+7;
int n,m;
int head[maxn],edge;
int a[maxn],ra[maxn];
bool vis[maxn];
int dis[maxn],dist[maxn],level[maxn];
struct EdgeNode
{
int to;
int w;
int next;
}edges[maxm];
void addedge(int u,int v,int w)
{
edges[edge].w=w;
edges[edge].to=v;
edges[edge].next=head[u];
head[u]=edge++;
}
void spfa(int floor)
{
for (int i=0;i<=n;i++)
dis[i]=INF;
memset(vis,0,sizeof(vis));
queue<int>Q;
Q.push(0);
vis[0]=true;
dis[0]=0;
while(!Q.empty())
{
int u=Q.front();
Q.pop();
vis[u]=false;
for(int i=head[u];i!=-1;i=edges[i].next)
{
int v=edges[i].to;
if((dis[v]>dis[u]+edges[i].w )&&ra[v]>=floor&&ra[v]<=floor+m)
{
dis[v]=dis[u]+edges[i].w;
if(!vis[v]) {vis[v]=true;Q.push(v);}
}
}
}
for(int i=0;i<n;i++)
if(dist[i]>dis[i]) dist[i]=dis[i];
///不断进行更新;
}
int main()
{
while(~scanf("%d %d",&m,&n))
{
for(int i=0;i<=n;i++)
{
dist[i]=INF;
head[i]=-1;
}
edge=0;
int levelnum=0;
for(int i=0;i<n;i++)
{
int num;
scanf("%d %d %d",&a[i],&ra[i],&num);
level[levelnum++]=ra[i];
for(int j=0;j<num;j++)
{
int w,x;
scanf("%d %d",&x,&w);
addedge(i,x-1,w);
}
}
///排序,删除重复元素;
sort(level,level+levelnum);
levelnum=unique(level,level+levelnum)-level;
for(int i=0;i<levelnum;i++)
if(ra[0]>=level[i]&&ra[0]<=level[i]+m)
spfa(level[i]);
/**
在满足等级差距的范围内找到进行SPFA;
*/
int ans=INF;
for(int i=0;i<n;i++)
ans=MIN(ans,dist[i]+a[i]);
printf("%d\n",ans);
}
return 0;
}
POJ - 1062 昂贵的聘礼 (等级限制,过程部分最优得到结果最优,SPFA)
最新推荐文章于 2020-11-02 22:32:14 发布