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 }

 

posted @ 2021-04-30 17:10  acmloser  阅读(46)  评论(0编辑  收藏  举报