zoukankan      html  css  js  c++  java
  • L2-001. 紧急救援

    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 }
  • 相关阅读:
    Android开发之Sqlite的使用
    ZOJ 3607 Lazier Salesgirl
    ZOJ 3769 Diablo III
    ZOJ 2856 Happy Life
    Ural 1119 Metro
    Ural 1146 Maximum Sum
    HDU 1003 Max Sum
    HDU 1160 FatMouse's Speed
    Ural 1073 Square Country
    Ural 1260 Nudnik Photographer
  • 原文地址:https://www.cnblogs.com/barrier/p/5546051.html
Copyright © 2011-2022 走看看