PKU 3463 Sightseeing

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],其他不更新。

代码:

 1  #include < stdio.h >
 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  }

你可能感兴趣的:(PKU 3463 Sightseeing)