類型:拓撲排序
題目:http://acm.hdu.edu.cn/showproblem.php?pid=2437
來源:2008 Asia Chengdu Regional Contest Online
思路:題目是求到某個滿足條件的節點的最短路且路徑長度爲k的倍數。使用二維數組dist[i][j]記錄當從源點到當前節點i且滿足路徑長度 % k = j時的最短路徑長度
則最終結果爲dist[i][0],i爲P節點且長度最小。
因爲該圖爲有向無環圖,所以從i點到j點路徑唯一,v節點的值只能由其前驅更新。所以可以以拓撲序列的順序更新圖中節點的dist值。
若dist[u][i]已知,則可以用dist[u][i] + w 更新f[v][(i + c) % k]的最優值。根據拓撲順序的性質,知道遞推式滿足無後效性。
初值dist[s][0] = 0。
// hdoj 2437 Jerboas
// re ac 109MS 4464K
#include <iostream>
#include <string>
#include <queue>
#include <stack>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;
#define FOR(i,a,b) for(i = (a); i < (b); ++i)
#define FORE(i,a,b) for(i = (a); i <= (b); ++i)
#define FORD(i,a,b) for(i = (a); i > (b); --i)
#define FORDE(i,a,b) for(i = (a); i >= (b); --i)
#define CLR(a,b) memset(a,b,sizeof(a))
#define PB(x) push_back(x)
const int MAXN = 1010;
const int MAXM = 20010;
const int hash_size = 25000002;
const int INF = 0x7f7f7f7f;
char str[MAXN];
int cnt, cas = 1;
int n, m, s, k;
int head[MAXN], ru[MAXN], dist[MAXN][MAXN];
struct edge {
int v, w, nxt;
}e[MAXM];
void addedge(int u, int v, int w) {
e[cnt].v = v;
e[cnt].w = w;
e[cnt].nxt = head[u];
head[u] = cnt++;
}
void topo() {
int i, j, u;
dist[s][0] = 0;
while(1) {
FORE(u, 1, n)
if(ru[u] == 0)
break;
if(u > n)
break;
for(i = head[u]; i != -1; i = e[i].nxt) {
int v = e[i].v;
--ru[v];
FOR(j, 0, k) {
if(dist[u][j] == -1)
continue;
int len = dist[u][j] + e[i].w;
int rem = len % k;
if(dist[v][rem] == -1 || dist[v][rem] > len)
dist[v][rem] = len;
}
}
ru[u] = -1;
}
}
void solve() {
int i;
int enddy = -1, enddz = -1;
topo();
FORE(i, 1, n) {
int tmpy = dist[i][0];
if(str[i] == 'P' && tmpy != -1 && (enddy == -1 || enddz > tmpy))
enddy = i, enddz = tmpy;
}
if(enddy == -1)
printf("Case %d: -1 -1\n", cas++);
else
printf("Case %d: %d %d\n", cas++, enddz, enddy);
}
void init() {
int i, u, v, w;
CLR(head, -1);
CLR(ru, 0);
CLR(dist, -1);
cnt = 0;
scanf("%d %d %d %d", &n, &m, &s, &k);
scanf("%s", str + 1);
FORE(i, 1, m) {
scanf("%d %d %d", &u, &v, &w);
addedge(u, v, w);
++ru[v];
}
}
int main() {
int t;
scanf("%d", &t);
while(t--) {
init();
solve();
}
return 0;
}