原题链接
考察:最短路+dp
md最短路计数变个形我就不会了,我是fw
思路:
首先明确当前u点的次短路 = u的最短路+road[i].w 或 u的次短路 +road[i].w .这道题实际不需要先求一遍最短路,然后再求一遍次短路及其条数.像求树的直径一样,次短路和最短路可以一次性求完.
只需要像的直径一样求最短路和次短路条数,再像最短路计数一样求条数.注意else if的先后顺序.
1 #include <iostream>
2 #include <cstring>
3 #include <queue>
4 using namespace std;
5 const int N = 1010,M = 10010;
6 typedef pair<int,int> PII;
7 int h[N],idx,n,m,dist[2][N],cnt[2][N];
8 bool st[2][N];
9 struct Road{
10 int to,ne,w;
11 }road[M];
12 struct Node{
13 int type,d,u;
14 bool operator>(const Node& n) const{
15 return this->d>n.d;
16 }
17 };
18 void add(int a,int b,int w)
19 {
20 road[idx].to = b,road[idx].w = w,road[idx].ne = h[a],h[a] = idx++;
21 }
22 void dijkstra(int s)
23 {
24 memset(dist,0x3f,sizeof dist);
25 memset(st,0,sizeof st);
26 memset(cnt,0,sizeof cnt);
27 priority_queue<Node,vector<Node>,greater<Node> > q;
28 dist[0][s] = 0;
29 cnt[0][s] = 1;
30 q.push({0,0,s});
31 while(q.size())
32 {
33 Node it = q.top();
34 q.pop();
35 int u = it.u,type = it.type;
36 if(st[type][u]) continue;
37 st[type][u] = 1;
38 for(int i=h[u];~i;i=road[i].ne)
39 {
40 int v = road[i].to;
41 if(dist[0][v]>dist[type][u]+road[i].w)
42 {
43 dist[1][v] = dist[0][v],cnt[1][v] = cnt[0][v];
44 cnt[0][v] = cnt[type][u];
45 dist[0][v] = dist[type][u]+road[i].w;
46 q.push({0,dist[0][v],v});
47 q.push({1,dist[1][v],v});
48 }else if(dist[0][v]==dist[type][u]+road[i].w) cnt[0][v] += cnt[type][u];
49 else if(dist[1][v]>dist[type][u]+road[i].w)
50 {
51 dist[1][v] = dist[type][u]+road[i].w;
52 cnt[1][v] = cnt[type][u];
53 q.push({1,dist[1][v],v});
54 }else if(dist[1][v]==dist[type][u]+road[i].w) cnt[1][v] += cnt[type][u];
55 }
56 }
57 }
58 int main()
59 {
60 int T;
61 scanf("%d",&T);
62 while(T--)
63 {
64 scanf("%d%d",&n,&m);
65 memset(h,-1,sizeof h); idx = 0;
66 while(m--)
67 {
68 int x,y,z; scanf("%d%d%d",&x,&y,&z);
69 add(x,y,z);
70 }
71 int s,e; scanf("%d%d",&s,&e);
72 dijkstra(s);
73 int ans = cnt[0][e];
74 if(dist[1][e]==dist[0][e]+1) ans+=cnt[1][e];
75 printf("%d\n",ans);
76 }
77 return 0;
78 }