思路:
有题目可知最终1号一定要在交易链中,所有可以通过1号的等级来划分出一些等级区间。
现在假设1号等级为v,等级区间的差为m,那么我们可以知道最终结果一定在
[v−m,v+m]
中,但是不能直接用这个区间去判定,因为这个区间长度大于了m,所以我们从
[v−m,v]
开始,
for(int i = 0;i <= m;i++){
[v-m+i,v+i]
}
每次只对在这个等级区间里点进行dijkstra,然后就没有什么卡点了。
#include <iostream>
#include <cstdio>
#include <string.h>
#include <queue>
using namespace std;
int rank[110];
int cost[110];// 一开始单独买的花费
int within[110];
int vis[110];
int dist[110];
int ma[110][110];
int m,n;
struct node{
int n,v;
node(){}
node(int nn,int vv){
n = nn ,v = vv;
}
};
bool operator < (const node& a,const node& b){
return a.v > b.v;
}
void dijkstra(){
priority_queue<node> q;
int pos;
for(int i = 1;i <= n;i++){
if(within[i] == 1){
q.push(node(i,dist[i]));
}
}
node te;
while(!q.empty()){
te = q.top();
if(vis[te.n] == 1){
q.pop();
continue;
}
else
vis[te.n] = 1;
q.pop();
for(int i = 1;i <= n;i++){
if(within[i] && !vis[i] && dist[te.n] + ma[te.n][i] < dist[i]){
dist[i] = dist[te.n] + ma[te.n][i];
q.push(node(i,dist[i]));
}
}
}
}
int main(){
cin>>m>>n;
memset(ma,0x3f,sizeof(ma));
for(int i = 1; i <= n;i++){
ma[i][i] = 0;
}
int a,b;
for(int i = 1;i <= n;i++){
int jj;
scanf("%d%d%d",&cost[i],&rank[i],&jj);
for(int j = 1;j <= jj;j++){
scanf("%d%d",&a,&b);
ma[a][i] = b;
}
}
int v = rank[1];
int ans = 0x3f3f3f3f;
for(int i = 0;i <= m;i++){
memset(within,0,sizeof(within));
memset(vis,0,sizeof(vis));
for(int j = 1;j <= n;j++){
if(rank[j] >= v-m+i && rank[j] <= v+i)
within[j] = 1;
}
for(int i = 1;i <= n;i++){
dist[i] = cost[i];
}
dijkstra();
if(ans > dist[1])
ans = dist[1];
}
printf("%d\n",ans);
}