題目大意:c++
給定 n m s t ;表示n個點編號爲0~n-1 m條邊 起點s終點tide
接下來一行給定n個數;表示第i個點的救援隊數量spa
接下來m行給定u v w;表示點u到點v有一條長度爲w的邊code
求從s到t的最短路有幾條blog
一條路上能夠集合的救援隊最多有多少it
輸出路徑event
#include <bits/stdc++.h> using namespace std; #define INF 0x3f3f3f3f #define LL long long #define inc(i,j,k) for(int i=j;i<=k;i++) #define dec(i,j,k) for(int i=j;i>=k;i--) #define gcd(i,j) __gcd(i,j) #define mem(i,j) memset(i,j,sizeof(i)) const int N=2e5+5; const int mod=1e9+7; int n,m,s,t; int V[N]; struct NODE{ int to,len; }; vector <NODE> G[N]; int dis[N], num[N]; int sumV[N], pre[N]; bool vis[N]; int main() { while(~scanf("%d%d%d%d",&n,&m,&s,&t)) { inc(i,0,n-1) scanf("%d",&V[i]); inc(i,0,n-1) G[i].clear(); while(m--) { int u,v,w; scanf("%d%d%d",&u,&v,&w); G[u].push_back({v,w}); G[v].push_back({u,w}); } mem(sumV,0); sumV[s]=V[s]; // 到i點的最短路可集合sumV[i]救援隊 mem(dis,INF); dis[s]=0; // 到i點的最短路長度爲dis[i] mem(num,0); num[s]=1; // 到i點的最短路有num[i]條 mem(pre,-1); mem(vis,0); // pre記錄路徑前驅 vis標記走過 while(1) { int u, mini=INF; inc(i,0,n-1) if(!vis[i] && dis[i]<mini) mini=dis[i], u=i; if(mini==INF) break; vis[u]=1; int all=G[u].size(); inc(i,0,all-1) { NODE v=G[u][i]; if(vis[v.to]) continue; if(dis[v.to]>dis[u]+v.len) { sumV[v.to]=sumV[u]+V[v.to]; dis[v.to]=dis[u]+v.len; num[v.to]=num[u]; pre[v.to]=u; } else if(dis[v.to]==dis[u]+v.len) { num[v.to]+=num[u]; if(sumV[v.to]<sumV[u]+V[v.to]) { sumV[v.to]=sumV[u]+V[v.to], pre[v.to]=u; } } } } printf("%d %d\n",num[t],sumV[t]); stack <int> s; int c=0; while(t!=-1) s.push(t), t=pre[t], c++; while(!s.empty()) { printf("%d",s.top()); s.pop(); if(--c==0) printf("\n"); else printf(" "); } } return 0; }