题目传送链接~~
分析一下题意和需要注意的坑点:
(1)建图问题 : 点权值和边权值,而且要注意的是本题中 每组交易都是单项的,所以要注意的是有向图,而且要反着建 可以这样理解:如何通过交易以最少的价格获得1(如何以最短的路径到达1)
(2)等级问题:枚举解决,我们枚举的是每个顶点从他开始到达1时的最小路径(交易花费的最小金额),因而我们可以以该点的等级为最大等级,在遍历各点,大于他或者与他相差过大的可以直接略过。
#include <stdio.h>
#include <iostream>
#include <cstring>
using namespace std;
const int maxn = 1000;
const int INF = 99999999;
int m, n, cost[maxn][maxn], rankon[maxn], d[maxn];
bool used[maxn];
int dijkstra()
{
for(int i = 0; i <= n; i++)
{
d[i] = cost[i][i];
}
while(true)
{
int v = -1;
for(int i = 1; i <= n; i++)
{
if(!used[i] && (v == -1 || d[i] < d[v]))
v = i;
}
if(v == -1)
break;
used[v] = true;
for(int i = 1; i <= n; i++)
{
if(!used[i] && d[v] + cost[v][i] < d[i])
d[i] = d[v] + cost[v][i];
}
}
return d[1];
}
void init()
{
for(int i = 0; i <= 110; i++) // 初始化cost数组
{
for(int j = 0; j <= 110; j++)
{
cost[i][j] = INF;
if(i == j)
cost[i][j] = 0;
}
}
for(int i = 1; i <= n; i++)
{
int a, b, c;
scanf("%d%d%d", &a, &b, &c); // 输入物品的价格 主人级别 和可替代商品数目
cost[i][i] = a; // 本身商品价格即点值
rankon[i] = b; //存储主人级别
for(int j = 0; j < c; j++)
{
int a,b;
scanf("%d%d", &a, &b);
cost[a][i] = b; // 单向图
}
}
}
int main()
{
while(scanf("%d%d", &m, &n) != EOF)
{
init();
int minx = 99999999;
memset(used, false, sizeof(used));
for(int i = 1; i <= n; i++)
{
int maxx = rankon[i]; // 以当前点为最大级别
for(int j = 1; j <= n; j++)
{
if(rankon[j] > maxx || maxx - rankon[j] > m)
{
used[j] = true; // 不合题意的情况设为true直接忽略掉
}
else
used[j] = false;
}
int temp = dijkstra(); // 因为是枚举级别 存储每一次的最小值
// cout<<"temp = "<<temp<<endl;
if(minx > temp)
{
minx = temp;
}
}
printf("%d\n",minx);
}
return 0;
}