A Za, A Za, Fighting...

坚信:勤能补拙

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, 0sizeof(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(in0sizeof(in));
38     memset(cnt, 0sizeof(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 }

posted on 2010-09-11 16:31 simplyzhao 阅读(249) 评论(0)  编辑 收藏 引用 所属分类: F_图算法


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


导航

<2010年9月>
2930311234
567891011
12131415161718
19202122232425
262728293012
3456789

统计

常用链接

留言簿(1)

随笔分类

随笔档案

搜索

最新评论

阅读排行榜

评论排行榜