PKU 3463 Sightseeing
http://acm.pku.edu.cn/JudgeOnline/problem?id=3463
思路:
该题不会,查看别人思路后发现又是DP+Dijkstra
DP真的是相当相当地强大啊...
参考:
http://hi.baidu.com/scameeling/blog/item/c06f15f0f44e3418b07ec5fe.html
http://www.cnblogs.com/zhangjinglei/archive/2009/07/31/1536160.html
转载:
dp[i][1]表示到达点i最短的路有多少条,dp[i][2]表示次短的条数
dist[i][1]表示到达点i最短路的长度,dist[i][2].........................
初始化为dist[st][1]=0 其他为max_int dp[st][1]=1 其他为0
用v去松驰u时有四种情况 (设当前dist[v][cas])
情况1:dist[v][cas]+w(v,u)<dist[u][1],找到一个更短的距离,则把原来最短的距离作为次短的距离,同时更新最短的.即
dist[u][2]=dist[u][1]
dist[u][1]=dist[v][cas]+w(v,u);
dp[u][2]=dp[u][1]
dp[u][1]=dp[v][cas],
把Node(dist[u][1],u,1)和Node(dist[u][2],u,2)放入队列
情况2:dist[v][cas]+w(v,u)==dist[u][1],找到一条新的相同距离的最短路,则dp[u][1]+=dp[v][cas],其他不用更新,也不入队
情况3:dist[v][cas]+w(v,u)<dist[u][2],不可以更新最短距离,但可以更新次短的,则更新dist[u][2]和dp[u][2]
dist[u][2]=dist[v][cas]+w(v,u);
dp[u][2]=dp[v][cas];
把Node(dist[u][2],u,2)放入队列
情况4:dist[v][cas]+w(v,u)==dist[u][2] 找到一条新的相同距离的次短路,则dp[u][2]+=dp[v][cas],其他不更新。
代码:
2 #include < stdlib.h >
3 #include < string .h >
4 #define MAX_N 1001
5 #define INF 0x7FFFFFFF
6 int d[MAX_N][ 2 ], in [MAX_N][ 2 ], cnt[MAX_N][ 2 ];
7 int n, m, from, to;
8 struct Node {
9 int target, cost;
10 struct Node * next;
11 };
12 struct Node * nodes[MAX_N]; /* adj list: there may be different roads between city A and city B */
13
14 void
15 init()
16 {
17 int i, f, t, c;
18 struct Node * fresh;
19 memset(nodes, 0 , sizeof (nodes));
20 scanf( " %d %d " , & n, & m);
21 for (i = 0 ; i < m; i ++ ) {
22 scanf( " %d %d %d " , & f, & t, & c);
23 fresh = ( struct Node * )malloc( sizeof ( struct Node));
24 fresh -> target = t;
25 fresh -> cost = c;
26 fresh -> next = nodes[f];
27 nodes[f] = fresh;
28 }
29 scanf( " %d %d " , & from, & to);
30 }
31
32 void
33 dijkstra()
34 {
35 int i, j, k, p, min, v, cur;
36 struct Node * tmp;
37 memset( in , 0 , sizeof ( in ));
38 memset(cnt, 0 , sizeof (cnt));
39 /* d[i][0]: minimum path, d[i][1]: second minimum path */
40 for (i = 1 ; i <= n; i ++ )
41 d[i][ 0 ] = d[i][ 1 ] = INF;
42 d[from][ 0 ] = 0 ;
43 cnt[from][ 0 ] = 1 ;
44 for (i = 1 ; i <= 2 * n; i ++ ) { /* each vertex has two chance to relax */
45 min = INF;
46 p = - 1 ;
47 for (j = 1 ; j <= n; j ++ ) {
48 if ( ! in [j][ 0 ] && d[j][ 0 ] < min) {
49 min = d[j][ 0 ];
50 p = j;
51 k = 0 ;
52 } else if ( ! in [j][ 1 ] && d[j][ 1 ] < min) {
53 min = d[j][ 1 ];
54 p = j;
55 k = 1 ;
56 }
57 }
58 if (p == - 1 )
59 break ;
60 in [p][k] = 1 ;
61 tmp = nodes[p];
62 while (tmp != NULL) { /* Relax */
63 v = tmp -> target;
64 cur = d[p][k] + tmp -> cost;
65 if (cur < d[v][ 0 ]) {
66 d[v][ 1 ] = d[v][ 0 ];
67 cnt[v][ 1 ] = cnt[v][ 0 ];
68 d[v][ 0 ] = cur;
69 cnt[v][ 0 ] = cnt[p][k];
70 } else if (cur == d[v][ 0 ]) {
71 cnt[v][ 0 ] += cnt[p][k];
72 } else if (cur < d[v][ 1 ]) {
73 d[v][ 1 ] = cur;
74 cnt[v][ 1 ] = cnt[p][k];
75 } else if (cur == d[v][ 1 ]) {
76 cnt[v][ 1 ] += cnt[p][k];
77 }
78 tmp = tmp -> next;
79 }
80 }
81 }
82
83 int
84 main( int argc, char ** argv)
85 {
86 int tests, rt;
87 scanf( " %d " , & tests);
88 while (tests -- ) {
89 init();
90 dijkstra();
91 rt = cnt[to][ 0 ];
92 if (d[to][ 0 ] + 1 == d[to][ 1 ])
93 rt += cnt[to][ 1 ];
94 printf( " %d\n " , rt);
95 }
96 }