poj 3463 Sightseeing
Description:
给出一张无向图,求最短路以及次短路条数之和。
思路:次短路什么的真的不是很会啊。看了别人的题解,然后发现可以用堆里面可以用一个三元组存储点的编号,距离,以及1和0分别表示最短路和次短路,然后跑的时候转移状态即可
#include<iostream> #include<queue> #include<cstring> #include<cstdio> using namespace std; const int N = 1010, M = 10040, INF = 1e9; struct node{ int u, d; bool f; bool operator < (const node& a)const{ return d > a.d; } }; int n, m, s, e, dp[N][2], dis[N][2]; bool vis[N][2]; int head[N], now; struct edges{ int to, next, w; }edge[M<<1]; void add(int u, int v, int w){ edge[++now] = {v, head[u], w}; head[u] = now;} void dij(int s,int e){ memset(dis, 0x3f, sizeof(dis)); memset(vis, 0, sizeof(vis)); priority_queue<node> heap; dis[s][0] = 0; heap.push((node){s, dis[s][0], 0}); dp[s][0] = 1; while(!heap.empty()){ node tmp = heap.top(); heap.pop(); int x = tmp.u, flag = tmp.f; if(vis[x][flag]) continue; vis[x][flag] = 1; for(int i = head[x]; i; i = edge[i].next){ int v = edge[i].to, temp = edge[i].w + dis[x][flag]; if(temp < dis[v][0]){ if(dis[v][0] < INF){ dis[v][1] = dis[v][0]; dp[v][1] = dp[v][0]; heap.push((node){v, dis[v][1], 1}); } dis[v][0] = temp; dp[v][0] = dp[x][flag]; heap.push((node){v, dis[v][0], 0}); } else if(temp == dis[v][0]) dp[v][0] += dp[x][flag]; else if(temp < dis[v][1]){ dis[v][1] = temp; dp[v][1] = dp[x][flag]; heap.push((node){v, dis[v][1], 1}); } else if(temp == dis[v][1]) dp[v][1] += dp[x][flag]; } } return ; } void init(){ memset(dis, 0 ,sizeof(dis)); memset(dp, 0, sizeof(dp)); memset(edge,0,sizeof(edge)); memset(head,0,sizeof(head)); now = 0; } int main(){ int T; scanf("%d",&T); while(T--){ scanf("%d%d",&n,&m); init(); int x, y, z; for(int i = 1; i <= m; i++){ scanf("%d%d%d",&x, &y, &z); add(x, y, z); } scanf("%d%d",&s, &e); dij(s, e); if(dis[e][1] - dis[e][0] == 1) printf("%d\n", dp[e][0] + dp[e][1]); else printf("%d\n", dp[e][0]); // printf("%d\n", dis[e][1]); } return 0; }