• 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 }
  • 相关阅读:
    k阶斐波那契数列fibonacci第n项求值
    PMP学习笔记--03项目范围管理
    PMP学习笔记--02项目整合管理
    PMP学习笔记--01项目管理概论
    Java学习笔记 -- 头代码
    Scrum Framework, Process and Story Point
    敏捷宣言(Agile Manifesto)和敏捷开发十二原则
    如何将excel文件导入testlink
    Robot Framework环境搭建
    Fiddler抓包工具的使用
  • 原文地址:https://www.cnblogs.com/barrier/p/5546051.html
Copyright © 2020-2023  润新知