题目链接: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 }
原文地址:https://www.cnblogs.com/yuanweidao/p/10961335.html
时间: 2024-10-03 05:56:07