AcWing 383. 观光
考察:最短路+dp
md最短路计数变个形我就不会了,我是fw
思路:
首先明确当前u点的次短路 = u的最短路+road[i].w 或 u的次短路 +road[i].w .这道题实际不需要先求一遍最短路,然后再求一遍次短路及其条数.像求树的直径一样,次短路和最短路可以一次性求完.
只需要像的直径一样求最短路和次短路条数,再像最短路计数一样求条数.注意else if的先后顺序.
有前面分析可知,我们需要用到u的最短路和次短路.所以本题次短路和最短路都要作为结点push进队列中,因此需要定义结点Node 包含 type,dist,结点编号.
这实际等效于将u拆成两点,因此st数组也需要用到二维.
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 }