用优惠价表示边,求最短路之后,求node【i】。p+dis【i】的最小值
要注意题目中的一句话但是如果他和某个地位较低的人进行了交易,地位较高的的人不会再和他交易,他们认为这样等于是间接接触,反过来也一样。所以,可以枚举等级区间,对每个区间来求最短路
AC代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define MAX 0x3f3f3f3f
struct Edge{
int weight, next, to;
};
struct Node{
int p, L;
};
Edge edge[20000];
int head[110], tot;
Node node[110];
int M, N, L, R;
void add_edge( int a, int b, int weight ){
edge[tot].to = b;
edge[tot].weight = weight;
edge[tot].next = head[a];
head[a] = tot++;
}
int dij(){
int dis[110];
bool mark[110];
memset( mark, false, sizeof( mark ) );
memset( dis, 0x3f, sizeof( dis ) );
dis[1] = 0;
mark[1] = true;
for( int i = head[1]; i != -1; i = edge[i].next ){
int to = edge[i].to;
if( node[to].L >= L && node[to].L <= R ){
dis[to] = edge[i].weight;
}
}
for( int i = 2; i <= N; i++ ){
int minid = -1, mindis = MAX;
for( int j = 1; j <= N; j++ ){
if( dis[j] < mindis && !mark[j] ){
minid = j;
mindis = dis[j];
}
}
if( minid == -1 ){
break;
}
mark[minid] = true;
for( int j = head[minid]; j != -1; j = edge[j].next ){
int to = edge[j].to;
int weight = edge[j].weight;
if( !mark[to] && dis[to] > dis[minid] + weight && node[to].L >= L && node[to].L <= R ){
dis[to] = dis[minid] + weight;
}
}
}
int ans = MAX;
for( int i = 1; i <= N; i++ ){
ans = min( ans, dis[i] + node[i].p );
}
return ans;
}
int main(){
while( scanf( "%d%d", &M, &N ) != EOF ){
memset( head, -1, sizeof( head ) );
tot = 0;
for( int i = 1; i <= N; i++ ){
int temp;
scanf( "%d%d%d", &node[i].p, &node[i].L, &temp );
for( int j = 1; j <= temp; j++ ){
int temp1, temp2;
scanf( "%d%d", &temp1, &temp2 );
add_edge( i, temp1, temp2 );
}
}
int ans = MAX;
for( L = node[1].L - M; L <= node[1].L; L++ ){
if( L >= 0 ){
R = L + M;
ans = min( ans, dij() );
}
}
cout << ans << endl;
}
return 0;
}