1. 程式人生 > >POJ 3463 Sightseeing (求最短路和次短路數量)

POJ 3463 Sightseeing (求最短路和次短路數量)

原題地址:http://poj.org/problem?id=3463
題意:給出一張有向圖,再給出一個起點和一個終點,詢問你從起點到終點的最短距離的和次短距離的邊(這裡要求次短距離和最短距離相差1)有幾條.

思路;只要開一個cnt陣列記錄邊的數量,dis陣列記錄最短路和次短路的值,然後對每一次是否可以進行鬆弛進行4次判斷即可.

#include <cmath>
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
#include <vector> #include <stack> #include <set> #include <cctype> #define eps 1e-8 #define INF 0x3f3f3f3f #define MOD 1e9+7 #define PI acos(-1) #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 #define CLR(x,y) memset((x),y,sizeof(x)) using namespace std; typedef
long long ll; typedef unsigned long long ull; const int maxn = 1e5 + 5; int n, m, t; struct edge { int v, w, nxt; } e[maxn]; int ecnt ; int head[maxn]; void init_head() { ecnt = 0; CLR(head, -1); } void add_edge(int u, int v, int w) { e[ecnt].v = v; e[ecnt].w = w; e[ecnt].nxt = head[u]; head[u] = ecnt++; } int
start, last; int cnt[maxn][2];//計算路徑數量 int dis[maxn][2];//記錄最短路,次短路距離的 //0 表示最短路,1表示次短路 struct node { int v, flag; //v表示當前位於哪個頂點,flag標記是最短路還是次短路 bool operator <(const node &a)const { return dis[v][flag] > dis[a.v][a.flag]; } node() {} node(int v, int flag): v(v), flag(flag) {} }; int vis[maxn][2]; int dij() { priority_queue<node>q; CLR(vis, 0); CLR(dis, 0x3f); CLR(cnt, 0); q.push(node(start, 0)); dis[start][0] = 0; cnt[start][0] = 1; while(!q.empty()) { int u = q.top().v; int flag = q.top().flag; q.pop(); if(vis[u][flag]) continue; vis[u][flag] = 1; for(int i = head[u]; ~i; i = e[i].nxt) { int v = e[i].v; if(dis[v][0] > dis[u][flag] + e[i].w) {//這裡分四種情況分類討論 if(dis[v][0] != INF) {//當前值比最短路小,不是特別懂這裡為什麼要加if dis[v][1] = dis[v][0]; cnt[v][1] = cnt[v][0]; q.push(node(v, 1)); } dis[v][0] = dis[u][flag] + e[i].w; cnt[v][0] = cnt[u][flag]; q.push(node(v, 0)); } else if(dis[v][0] == dis[u][flag] + e[i].w) {//當前值和最短路相同 cnt[v][0] += cnt[u][flag]; } else if(dis[v][1] > dis[u][flag] + e[i].w) {//當前比次短路小 dis[v][1] = dis[u][flag] + e[i].w; cnt[v][1] = cnt[u][flag]; q.push(node(v, 1)); } else if(dis[v][1] == dis[u][flag] + e[i].w) {//當前值和次短路相同 cnt[v][1] += cnt[u][flag]; } } } int num = cnt[last][0]; if(dis[last][1] - 1 == dis[last][0]) num += cnt[last][1]; return num; } int main() { scanf("%d", &t); while(t--) { scanf("%d%d", &n, &m); init_head(); for(int i = 1; i <= m; i++) { int u, v, w; scanf("%d%d%d", &u, &v, &w); add_edge(u, v, w); } scanf("%d%d", &start, &last); printf("%d\n", dij()); } return 0; }