HDU 1688 Sightseeing 【输出最短路+次短路条数】

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1688

题目大意:给n个点,m条有向边。再给出起点s, 终点t。求出s到t的最短路条数+次短路条数

思路:

1.最短路和次短路是紧密相连的,在最短路松弛操作中,当我们找到一条更短的路径,也就意味着之前的路径不再是最短路,而成为了次短路,利用这个关系可以实现状态的转移。

2.好久没写优先队列了,都忘记了加个 priority_queue, 这样才能写重载,才能排序。

注释在代码里:

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<queue>
  4 #define mem(a, b) memset(a, b, sizeof(a))
  5 const int inf = 0x3f3f3f3f;
  6 using namespace std;
  7 
  8 int n, m;
  9 int tot, head[1100];
 10 int dis[2][1100], cnt[2][1100];//dis数组记录最短路 0 和次短路 1 距离,cnt数组记录最短路 0 和次短路 1 条数 
 11 int vis[2][1100];
 12 
 13 struct Edge
 14 {
 15     int to, next;
 16     int w;
 17 }edge[100010];
 18 
 19 void add(int a, int b, int w)
 20 {
 21     edge[++ tot].to = b;
 22     edge[tot].w = w;
 23     edge[tot].next = head[a];
 24     head[a] = tot;
 25 }
 26 
 27 struct Node//优先队列优化结构体,id为点的序号, dis为源点到该点的距离 p区分属于最短路还是次短路 
 28 {
 29     int id, dis, p;
 30     bool operator < (const Node &a)const
 31     {
 32         return dis > a.dis; 
 33     }
 34 }node[1100];
 35 
 36 void init()
 37 {
 38     mem(head, -1), tot = 0;
 39     mem(vis, 0);  //代表源点到该点的距离未被确定 
 40 }
 41 
 42 void dij(int s, int t)
 43 {
 44     priority_queue<Node> Q;
 45     while(!Q.empty())
 46         Q.pop();
 47     for(int i = 1; i <= n; i ++) //初始化 
 48     {
 49         dis[0][i] = dis[1][i] = inf;
 50         cnt[0][i] = cnt[1][i] = 0;
 51     }
 52     dis[0][s] = 0;
 53     cnt[0][s] = 1;//源点到自己的最短路条数为1 
 54     Node temp;
 55     temp.p = 0, temp.dis = 0, temp.id = s;
 56     Q.push(temp);
 57     while(!Q.empty())
 58     {
 59         Node a = Q.top();
 60         Q.pop();
 61         if(vis[a.p][a.id])
 62             continue; //该p状态下已经确定过就跳过 
 63         vis[a.p][a.id] = 1;
 64         for(int i = head[a.id]; i != -1; i = edge[i].next)
 65         {
 66             int to = edge[i].to;
 67             if(dis[0][to] > dis[a.p][a.id] + edge[i].w) //最短路可以更新(在0或1状态下找到一条更短的路) 
 68             {
 69                 dis[1][to] = dis[0][to];  //原来的最短路成为次短路
 70                 dis[0][to] = dis[a.p][a.id] + edge[i].w;
 71                 cnt[1][to] = cnt[0][to];//次短路条数继承为原来的最短路条数 
 72                 cnt[0][to] = cnt[a.p][a.id];
 73                 temp.p = 0, temp.dis = dis[0][to], temp.id = to;
 74                 Q.push(temp);
 75                 temp.p = 1, temp.dis = dis[1][to], temp.id = to;
 76                 Q.push(temp);
 77             }
 78             else if(dis[0][to] == dis[a.p][a.id] + edge[i].w)//最短路长度一样 更新最短路条数即可 
 79             {
 80                 cnt[0][to] += cnt[a.p][a.id];
 81             }
 82             else if(dis[1][to] > dis[a.p][a.id] + edge[i].w)//找到一条长度大于最短路但小于当前次短路的路径 
 83             {//将这条路变成次短路 
 84                 dis[1][to] = dis[a.p][a.id] + edge[i].w;
 85                 cnt[1][to] = cnt[a.p][a.id];
 86                 temp.p = 1, temp.dis = dis[1][to], temp.id = to;
 87                 Q.push(temp);
 88             }
 89             else if(dis[1][to] == dis[a.p][a.id] + edge[i].w)
 90             {
 91                 cnt[1][to] += cnt[a.p][a.id];
 92             }
 93         }
 94     }
 95 }
 96 
 97 int main()
 98 {
 99     int T;
100     scanf("%d", &T);
101     while(T --)
102     {
103         init();
104         scanf("%d%d", &n, &m);
105         for(int i = 1; i <= m; i ++)
106         {
107             int a, b, c;
108             scanf("%d%d%d", &a, &b, &c);
109             add(a, b, c);
110         }
111         int s, t;
112         scanf("%d%d", &s, &t);
113         dij(s, t);
114         int ans = cnt[0][t]; //ans代表最短路的条数
115         if(dis[0][t] + 1 == dis[1][t])
116             ans += cnt[1][t];
117         printf("%d\n", ans); 
118     }
119     return 0;
120 }
View Code

猜你喜欢

转载自www.cnblogs.com/yuanweidao/p/10961335.html
今日推荐