因为有花费的限制,所有存最短路的数组改为d[i][j],代表走到i点还剩余j的钱的最短路的值,
relax时做一个剪枝,第一个条件是剩余钱数大于通过当前边所需的钱,第二,即将更新的
值要小于当前到达N点的最短路的值。在更新最短值的时候,走过一条边要将钱数也更新
,即剩余money 减去过路费。
/*Accepted 1936K 188MS C++ 1701B 2012-07-27 12:00:50*/ #include<cstdio> #include<cstring> #include<cstdlib> #include<queue> #include<iostream> using namespace std; const int MAXN = 1 << 7, MAXR = 1 << 14; const int inf = 0x3f3f3f3f; int u[MAXR], v[MAXR], w[MAXR], tol[MAXR], head[MAXN], nxt[MAXR]; int d[MAXN][MAXR]; int K, N, R; bool inq[MAXN][MAXR] = {false}; struct Node { int dist, money, x; }; void ReadGraph() { memset( head, -1, sizeof head); for( int i = 0; i < R; i ++ ) { int s, e, l, t; scanf( "%d%d%d%d", &s, &e, &l, &t); u[i] = s, v[i] = e, w[i] = l, tol[i] = t; nxt[i] = head[s], head[s] = i; } } int spfa() { queue<Node> q; int ans = inf, i, j; Node f, g; //bool inq[MAXN][MAXR] = {false}; 在函数内是不能定义大数组的,在这里浪费了大半个小时 for( i = 1; i <= N; i ++) for( j = 0; j <= K; j ++) d[i][j] = inf, inq[i][j] = false; f.x = 1, f.money = K, f.dist = 0; d[1][K] = 0; q.push(f), inq[1][K] = true; while( !q.empty()) { f = q.front(), q.pop(); inq[f.x][f.money] = false; if( f.x == N && d[f.x][f.money] < ans) ans = d[f.x][f.money]; for( i = head[f.x]; i != -1; i = nxt[i]) { if(f.money >= tol[i] && d[f.x][f.money] + w[i] < ans && d[f.x][f.money] + w[i] < d[v[i]][f.money - tol[i]]) { g.dist = d[f.x][f.money] + w[i]; g.money = f.money - tol[i]; g.x = v[i]; if(!inq[g.x][g.money]) q.push(g), inq[g.x][g.money] = true; d[g.x][g.money] = g.dist; } } } if( ans == inf) ans = -1; return ans; } int main() { while( scanf( "%d%d%d", &K, &N, &R) != EOF) { ReadGraph(); printf( "%d\n", spfa()); } return 0; }