1. 程式人生 > >PAT 團體程式設計天梯賽-練習集 L2-001. 緊急救援 【dijkstra】

PAT 團體程式設計天梯賽-練習集 L2-001. 緊急救援 【dijkstra】

題目連結

思路

題意是求個最短路,要求路徑長度和最短的前提下,點權和最大,並求出長度相等的最短路有幾條,並輸出路徑,是dijkstra的靈活運用。

這種題好像寫過很多遍了,但這次還是不能一次過,除錯了半天。

點權和最大很好解決,給dis加一個屬性就可以了。

輸出最短路徑,可以用一個數組記錄每個點的前驅。

最短路有幾條卡了挺久,方法是對每個點設一個cnt記錄到這個點的最短路徑有幾條,
然後每次更新dis,如果路徑長相等,就加上前驅點的cnt,否則如果新路徑更短,就置為前驅點的cnt。

AC程式碼

#include <iostream>
#include <cstring>
#include <vector> using namespace std; const int INF=0x3f3f3f3f; int w[600]; int g[600][600]; int n,m,s,d; struct node { node() { l=INF; w=0; } node(int _l, int _w) { w=_w; l=_l; } bool friend operator < (node a, node b) { if
(a.l==b.l) return a.w>b.w; return a.l<b.l; } int w,l; }dis[600]; bool vis[600]; int cnt[600]; int pre[600]; void dijkstra(int start) { dis[start].l=0; dis[start].w=w[start]; for(int i=0 ; i<n ; ++i) { node min_node(INF,0); int u=-1; for
(int j=0 ; j<n ; ++j) { if(vis[j]==0 && dis[j]<min_node) { min_node=dis[j]; u=j; } } for(int v=0 ; v<n ; ++v) { if(vis[v]==0 && g[u][v]<INF) { node new_dis=node(dis[u].l+g[u][v], dis[u].w+w[v]); if(new_dis.l==dis[v].l) { cnt[v]+=cnt[u]; } if(new_dis.l<dis[v].l) { cnt[v]=cnt[u]; } if(new_dis<dis[v]) { dis[v]=new_dis; pre[v]=u; } } } vis[u]=1; } } void init() { for(int i=0 ; i<600 ; ++i) cnt[i]=1; memset(g,INF,sizeof g); memset(pre,-1,sizeof pre); } int main() { init(); scanf("%d%d%d%d",&n,&m,&s,&d); for(int i=0 ; i<n ; ++i) { scanf("%d",&w[i]); } for(int i=0 ; i<m ; ++i) { int u,v,l; scanf("%d%d%d",&u,&v,&l); g[u][v]=g[v][u]=l; } dijkstra(s); int t=d; vector<int>ans; while(pre[t]!=-1) { ans.push_back(t); t=pre[t]; } ans.push_back(s); printf("%d %d\n",cnt[d], dis[d].w); for(int i=ans.size()-1 ; i>=0 ; --i) { if(i==(int)ans.size()-1)printf("%d",ans[i]); else printf(" %d",ans[i]); } printf("\n"); return 0; }