1. 程式人生 > >L2-001 緊急救援

L2-001 緊急救援

clas eve math max show ret 一道 開始 urn

這題是一道給我這個菜雞復習Dijkstra的好題。

因為要求比較多,先把大致需要的數組羅列一下。

dis[]記錄最短路

path[]記錄路徑

pnum[]記錄最短路數目

cnt[]記錄最多人數

vis[]記錄是否走過這個點

首先需要將vis和cnt置零,dis置∞(用鄰接矩記錄邊也要記得置∞)

接著對起始點初始化,dis[s]=0;path[s]=-1;pnum[s]=1;cnt[s]=s點人數;

從每個點開始,先遍歷所有點,如果找到一個沒有被訪問過的並且距離更近的點,將這點作為起點,進行松弛操作

松弛操作有兩種情況,一種是距離較大的情況,更新各個數組即可。如果距離相等,要將兩者的pnum[]和cnt[]相加。

因為用了數組記錄最短路的每個點前一個節點,所以打印路徑遞歸即可,詳見代碼

技術分享圖片
#include <iostream>
#include <string.h>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <math.h>
#include <queue>
#include <vector>
#define maxn 605
#define INF 0x3f3f3f3f
using namespace
std; typedef long long ll; int num[maxn],dis[maxn],path[maxn],pnum[maxn],vis[maxn]; int ma[maxn][maxn]; int n,m,s,d,u,v,w; int cnt[maxn]; void dijkstra() { memset(vis,0,sizeof(vis)); memset(cnt,0,sizeof(cnt)); for(int i=0;i<n;i++) dis[i]=INF; dis[s]=0; path[s]
=-1; pnum[s]=1; cnt[s]=num[s]; for(int i=0;i<n;i++) { int t,minn=INF; for(int j=0;j<n;j++) { if(!vis[j]&&dis[j]<minn) { t=j; minn=dis[j]; } } vis[t]=1; for(int j=0;j<n;j++) { if(dis[j]>dis[t]+ma[t][j]) { dis[j]=dis[t]+ma[t][j]; path[j]=t; cnt[j]=cnt[t]+num[j]; pnum[j]=pnum[t]; } else if(dis[j]==dis[t]+ma[t][j]) { pnum[j]+=pnum[t]; if(cnt[j]<cnt[t]+num[j]) { cnt[j]=cnt[t]+num[j]; path[j]=t; } } } } } void print(int x) { if(path[x]==-1) { printf("%d",x); return; } print(path[x]); printf(" %d",x); return; } int main() { scanf("%d%d%d%d",&n,&m,&s,&d); memset(ma,INF,sizeof(ma)); for(int i=0;i<n;i++) scanf("%d",&num[i]); for(int i=0;i<m;i++) { scanf("%d%d%d",&u,&v,&w); ma[u][v]=w; ma[v][u]=w; } dijkstra(); printf("%d %d\n",pnum[d],cnt[d]); print(d); return 0; }
View Code

L2-001 緊急救援