POJ 3463 Sightseeing

题目链接: http://acm.hust.edu.cn/vjudge/contest/view.action?cid=110697#problem/A

-------------------------------------------------------------------------------------------------------

给定一个有向正权图和起点终点 求最短路以及比最短路长$1$的路径的个数(允许一条边走两次)

 

我们知道 $dijkstra$ 是基于一种贪心的思想 当某点成为当前所有未被使用的点中距离最近的点时

它就可以开始用来更新其他的点 并且它的距离是不可能再改变的

如果要求路径数的话 到这个点的最短路径的数量显然也是不会再变的

因此记录最短路径数量就有点像$DAG$上做的$dp$

 

至于求次短路 我们可以把每个点的次短路单独抽出来作为新的$n$个点(不过仍然受原来的求最短路的点影响)

这样在新的图上跑最短路就可以一次同时得到最短路和次短路了

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cmath>
 4 #include <algorithm>
 5 using namespace std;
 6 const int N = 1010, E = 10010;
 7 int firste[N], nexte[E], v[E], w[E];
 8 int dist[N << 1], cnt[N << 1];
 9 bool used[N << 1];
10 int t, n, m, e;
11 void build(int x,int y, int z)
12 {
13     nexte[++e] = firste[x];
14     firste[x] = e;
15     v[e] = y;
16     w[e] = z;
17 }
18 void dijkstra(int s)
19 {
20     memset(dist, 0x3f, sizeof dist);
21     memset(cnt, 0, sizeof cnt);
22     memset(used, 0, sizeof used);
23     dist[s] = 0;
24     cnt[s] = 1;
25     int u = s, tu, mdist;
26     for(int tt = 1; tt < n * 2; ++tt)
27     {
28         mdist = 1e9 + 10;
29         used[u] = 1;
30         if(u <= n)
31             for(int p = firste[u]; p; p = nexte[p])
32             {
33                 if(dist[v[p]] > dist[u] + w[p])
34                 {
35                     dist[v[p] + n] = dist[v[p]];
36                     cnt[v[p] + n] = cnt[v[p]];
37                     dist[v[p]] = dist[u] + w[p];
38                     cnt[v[p]] = cnt[u];
39                 }
40                 else if(dist[v[p]] == dist[u] + w[p])
41                     cnt[v[p]] += cnt[u];
42                 else if(dist[v[p] + n] > dist[u] + w[p])
43                 {
44                     dist[v[p] + n] = dist[u] + w[p];
45                     cnt[v[p] + n] = cnt[u];
46                 }
47                 else if(dist[v[p] + n] == dist[u] + w[p])
48                     cnt[v[p] + n] += cnt[u];
49             }
50         else
51             for(int p = firste[u - n]; p; p = nexte[p])
52             {
53                 if(dist[v[p] + n] > dist[u] + w[p])
54                 {
55                     dist[v[p] + n] = dist[u] + w[p];
56                     cnt[v[p] + n] = cnt[u];
57                 }
58                 else if(dist[v[p] + n] == dist[u] + w[p])
59                     cnt[v[p] + n] += cnt[u];
60             }
61         for(int i = 1; i <= n * 2; ++i)
62             if(!used[i] && dist[i] < mdist)
63             {
64                 mdist = dist[i];
65                 tu = i;
66             }
67         u = tu;
68     }
69 }
70 int main()
71 {
72     scanf("%d", &t);
73     while(t--)
74     {
75         e = 1;
76         memset(firste, 0, sizeof firste);
77         scanf("%d%d", &n, &m);
78         int x, y, z;
79         while(m--)
80         {
81             scanf("%d%d%d", &x, &y, &z);
82             build(x, y, z);
83         }
84         int s, f;
85         scanf("%d%d", &s, &f);
86         dijkstra(s);
87         printf("%d\n", cnt[f] + cnt[f + n] * (dist[f + n] == dist[f] + 1));
88     }
89     return 0;
90 }

 

posted @ 2016-03-28 07:59  sagitta  阅读(372)  评论(0编辑  收藏  举报