poj1062 昂贵的聘礼 **

/*
* 最短路, Dijkstra(数组实现)
*
* 建图 : 若 物品u 能用物品 v 再加 钱 a 交换, 则 边权值w(v,u) = a
* 初始: d[i] = 物品i的直接价格
*
* 注意等级的限制, 酋长的等级不一定是最高的~ 应枚举等级的范围,起点不在范围内的边不能松弛~
*
*
*/
#include
<cstdio>
#include
<cstring>
using namespace std;

const int inf = 10000000;
const int maxN = 100 + 5;
int m, n, r[maxN], d[maxN];
bool s[maxN];

struct SAdj{
int num, w;
SAdj
*next;
};
SAdj adj[maxN];


int Dijkstra(int low, int up){
memset(s,
0, sizeof(s));
int left = n;
for(int i=1; i<=n; i++)
if(r[i] < low || r[i] > up){//不在等级范围内,则直接把点放进s数组里
s[i] = 1; left--;
}

int tmpD[maxN];
memcpy(tmpD, d,
sizeof(d));

while(left--){
int tmpMin = inf, tmpMinNum;
for(int i=1; i<=n; i++){
if(!s[i] && tmpD[i] < tmpMin){
tmpMin
= tmpD[i]; tmpMinNum = i;
}
}
s[tmpMinNum]
= 1;
SAdj
*cur = adj[tmpMinNum].next;
while(cur != NULL){
if(tmpD[cur->num] > tmpD[tmpMinNum] + cur->w){
tmpD[cur
->num] = tmpD[tmpMinNum] + cur->w;
}
cur
= cur->next;
}
}

return tmpD[1];
}


int main(){
scanf(
"%d%d", &m, &n);

for(int i=1; i<=n; i++)
adj[i].next
= NULL;

int P, L, X, T, V;
for(int i=1; i<=n; i++){
scanf(
"%d%d%d", &P, &L, &X);
d[i]
= P;
r[i]
= L;

for(int j=1; j<=X; j++){
scanf(
"%d%d", &T, &V);

//邻接表
SAdj *node = new SAdj;
node
->num = i, node->w = V;
node
->next = adj[T].next;
adj[T].next
= node;
}
}

int ans = inf;
int low = r[1] - m, up = r[1]; //枚举等级的范围
for(int i=0; i<=m; i++){
int tmpAns = Dijkstra(low + i, up + i);
if(ans > tmpAns)
ans
= tmpAns;
}

printf(
"%d\n", ans);

return 0;
}
原文地址:https://www.cnblogs.com/longdouhzt/p/2165447.html