L2-001. 紧急救援
题目链接:https://www.patest.cn/contests/gplt/L2-001
Dijstra
本题是dijstra的拓展,在求最短路的同时,增加了不同的最短路径的条数和能够召集的最多的救援队数量。由于初学此算法,我先找了题练习(http://poj.org/problem?id=2387)。
代码如下:
1 #include<cstdio> 2 #include<stack> 3 #define N 505 4 #define MAX 5000 5 using namespace std; 6 int n,m,s,d; 7 int pro[N]; 8 int Map[N][N]; 9 bool mark[N]; 10 int sum[N]; 11 int path[N]; 12 int Distance[N]; 13 int person[N]; 14 int i,j; 15 stack<int>st; 16 int main(void){ 17 freopen("in.txt","r",stdin); 18 scanf("%d%d%d%d",&n,&m,&s,&d); 19 for(i=0;i<n;++i)scanf("%d",&pro[i]); 20 for(i=0;i<n;++i) 21 for(j=0;j<n;++j)Map[i][j]=MAX; 22 while(m--){ 23 int len; 24 scanf("%d%d%d",&i,&j,&len); 25 if(Map[i][j]>len)Map[i][j]=Map[j][i]=len; 26 } 27 for(i=0;i<n;++i){ 28 Distance[i]=MAX; 29 sum[i]=1; 30 person[i]=pro[s]; 31 if(Map[s][i]<MAX){ 32 Distance[i]=Map[s][i]; 33 path[i]=s; 34 person[i]+=pro[i]; 35 } 36 } 37 mark[s]=1,Distance[s]=0; 38 while(1){ 39 int k,m=MAX; 40 for(i=0;i<n;++i){ 41 if(!mark[i]&&m>Distance[i]){ 42 m=Distance[i]; 43 k=i; 44 } 45 } 46 if(m==MAX)break; 47 mark[k]=1; 48 for(i=0;i<n;++i){ 49 if(!mark[i]){ 50 if(Distance[i]>Distance[k]+Map[k][i]){ 51 Distance[i]=Distance[k]+Map[k][i]; 52 person[i]=person[k]+pro[i]; 53 path[i]=k; 54 sum[i]=sum[k]; 55 }else if(Distance[i]==Distance[k]+Map[k][i]){ 56 sum[i]+=sum[k]; 57 if(person[i]<person[k]+pro[i]){ 58 person[i]=person[k]+pro[i]; 59 path[i]=k; 60 } 61 } 62 } 63 } 64 } 65 int temp=pro[d]; 66 int k=d; 67 while(k!=s){ 68 st.push(k); 69 k=path[k]; 70 temp+=pro[k]; 71 } 72 printf("%d %d ",sum[d],temp); 73 printf("%d",s); 74 while(!st.empty()){ 75 printf(" %d",st.top()); 76 st.pop(); 77 } 78 printf(" "); 79 return 0; 80 }
上面普通dijkstra算法的复杂度是O(n^2)的,而可以用优先队列将其优化到O(nlgn),代码如下:
1 #include <iostream> 2 #include <queue> 3 #include <vector> 4 #define N 505 5 using namespace std; 6 const int inf=0x3fffffff; 7 int n,m,s,d,p[N],pre[N],dis[N],per[N],num[N]; 8 bool vis[N]; 9 struct edge{int to,w;}; 10 vector<edge>e[N]; 11 struct node{ 12 int u,d; 13 bool operator < (const node x)const{return d>x.d;} 14 }; 15 priority_queue<node>q; 16 void dij(int s){ 17 for(int i=0;i<n;++i)dis[i]=inf; 18 dis[s]=0;per[s]=p[s];num[s]=1;pre[s]=-1; 19 q.push((node){s,0}); 20 while(!q.empty()){ 21 node t=q.top();q.pop(); 22 int u=t.u; 23 if(vis[u])continue; 24 vis[u]=1; 25 for(int i=0;i<(int)e[u].size();++i){ 26 int v=e[u][i].to,w=e[u][i].w; 27 28 if(dis[u]+w==dis[v])num[v]+=num[u]; 29 if(dis[u]+w<dis[v])num[v]=num[u]; 30 31 if( (dis[u]+w==dis[v]&&per[u]+p[v]>per[v]) 32 ||dis[u]+w<dis[v]){ 33 dis[v]=dis[u]+w; 34 per[v]=per[u]+p[v]; 35 pre[v]=u; 36 q.push((node){v,dis[v]}); 37 } 38 } 39 } 40 } 41 void dfs(int k){ 42 if(k==-1)return; 43 dfs(pre[k]); 44 cout<<k<<" "; 45 } 46 int main(void){ 47 std::ios::sync_with_stdio(false); 48 cin>>n>>m>>s>>d; 49 for(int i=0;i<n;++i)cin>>p[i]; 50 for(int i=0;i<m;++i){ 51 int u,v,w; 52 cin>>u>>v>>w; 53 e[u].push_back((edge){v,w}); 54 e[v].push_back((edge){u,w}); 55 } 56 dij(s); 57 cout<<num[d]<<" "<<per[d]<<" "; 58 dfs(pre[d]); 59 cout<<d<<endl; 60 }