[patl2-001]紧急救援

解题关键:最短路的变形。

1、按顶点存储,$O(n^2)$

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<iostream>
#include<cmath>
#include<vector>
#define inf 0x3f3f3f3f
#define max_v 502
using namespace std;
typedef long long ll;
int pre[max_v],pathnum[max_v],toval[max_v],val[max_v];
int cost[max_v][max_v],d[max_v],used[max_v],V;
void dijkstra(int s){  //边权和点权都是通过顶点体现
    fill(d,d+V,inf);
    fill(used,used+V,0);
    fill(pre,pre+V,-1);
    
    d[s]=0;
    pathnum[s]=1;
    toval[s]=val[s];
    
    while(true){
        int v=-1;
        for(int u=0;u<V;u++){
            if(!used[u]&&(v==-1||d[u]<d[v])) v=u;
        }
        
        if(v==-1) break;
        used[v]=true;
        
        for(int u=0;u<V;u++){
            if(used[u]==false&&cost[u][v]!=inf){//????
                if(d[u]>d[v]+cost[v][u]){
                    d[u]=d[v]+cost[v][u];
                    pre[u]=v;
                    pathnum[u]=pathnum[v];
                    toval[u]=toval[v]+val[u];
                }else if(d[u]==d[v]+cost[v][u]){
                    pathnum[u]+=pathnum[v];
                    if(toval[u]<toval[v]+val[u]){
                        pre[u]=v;
                        toval[u]=toval[v]+val[u];
                    }
                }
            }
        }
    }
}
vector<int> get_path(int t){
    vector<int>path;
    for(;t!=-1;t=pre[t]) path.push_back(t);
    reverse(path.begin(), path.end());
    return path;
}

int N,M,S,D;
int main(){
    cin>>N>>M>>S>>D;
    V=N;
    for(int i=0;i<N;i++)   cin>>val[i];
    for(int i=0;i<V;i++){
        for(int j=0;j<V;j++){
            if(i!=j) cost[i][j]=cost[i][j]=inf;
        }
    }
    for(int i=0;i<M;i++){
        int a,b,c;
        cin>>a>>b>>c;
        cost[a][b]=cost[b][a]=c;
    }
    dijkstra(S);
    printf("%d %d
",pathnum[D],toval[D]);
    vector<int>path=get_path(D);
    for(int i=0;i<path.size();i++){
        printf("%d%c",path[i],i==path.size()-1?'
':' ');
    }
    return 0;
}

 2、按边存储 $O(nlogn)$

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<vector>
#include<queue>
#define max_v 502
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
struct edge{
    int to,cost;
};
typedef pair<int,int>P;//按边存储,默认不可以自己到自己进行dp
int V,pre[max_v],pathnum[max_v],val[max_v],toval[max_v];
vector<edge>G[max_v];
int d[max_v];
void dijkstra(int s){
    priority_queue<P,vector<P>,greater<P> >que;
    fill(d,d+V,inf);
    fill(pre,pre+V,-1);
    toval[s]=val[s];
    pathnum[s]=1;
    d[s]=0;
    que.push(P(0,s));
    while(!que.empty()){
        P p=que.top();que.pop();
        int v=p.second;
        if(d[v]<p.first) continue;
        for(int i=0;i<G[v].size();i++){
            edge e=G[v][i];
            if(d[e.to]>d[v]+e.cost){
                d[e.to]=d[v]+e.cost;
                pathnum[e.to]=pathnum[v];
                toval[e.to]=toval[v]+val[e.to];
                pre[e.to]=v;
                que.push(P(d[e.to],e.to));
            }else if(d[e.to]==d[v]+e.cost){
                pathnum[e.to]+=pathnum[v];
                if(toval[e.to]<toval[v]+val[e.to]){
                    toval[e.to]=toval[v]+val[e.to];
                    pre[e.to]=v;
                }
            }
        }
    }
}

vector<int> get_path(int t){
    vector<int>path;
    for(;t!=-1;t=pre[t]) path.push_back(t);
    reverse(path.begin(), path.end());
    return path;
}


int N,M,S,D;
int main(){
    cin>>N>>M>>S>>D;
    V=N;
    for(int i=0;i<N;i++)   cin>>val[i];
    for(int i=0;i<M;i++){
        int a,b,c;
        cin>>a>>b>>c;
        G[a].push_back((edge){b,c});
        G[b].push_back((edge){a,c});
    }
    dijkstra(S);
    printf("%d %d
",pathnum[D],toval[D]);
    vector<int>path=get_path(D);
    for(int i=0;i<path.size();i++){
        printf("%d%c",path[i],i==path.size()-1?'
':' ');
    }
    return 0;
}

 3、代码三

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<iostream>
#include<cmath>
#include<vector>
#define inf 0x3f3f3f3f
#define max_v 502
using namespace std;
typedef long long ll;
int pre[max_v],pathnum[max_v],toval[max_v],val[max_v];
int cost[max_v][max_v],d[max_v],used[max_v],V;
void dijkstra(int s){  //边权和点权都是通过顶点体现
    fill(d,d+V,inf);
    fill(used,used+V,0);
    fill(pre,pre+V,-1);
    
    d[s]=0;
    pathnum[s]=1;
    toval[s]=val[s];
    
    while(true){
        int v=-1;
        for(int u=0;u<V;u++){
            if(!used[u]&&(v==-1||d[u]<d[v])) v=u;
        }
        
        if(v==-1) break;
        used[v]=true;
        
        for(int u=0;u<V;u++){
            if(d[u]>d[v]+cost[v][u]){
                d[u]=d[v]+cost[v][u];
                pre[u]=v;
                pathnum[u]=pathnum[v];
                toval[u]=toval[v]+val[u];
            }else if(d[u]==d[v]+cost[v][u]){
                pathnum[u]+=pathnum[v];
                if(toval[u]<toval[v]+val[u]){
                    pre[u]=v;
                    toval[u]=toval[v]+val[u];
                }
            }
        }
    }
}
vector<int> get_path(int t){
    vector<int>path;
    for(;t!=-1;t=pre[t]) path.push_back(t);
    reverse(path.begin(), path.end());
    return path;
}

int N,M,S,D;
int main(){
    cin>>N>>M>>S>>D;
    V=N;
    for(int i=0;i<N;i++)   cin>>val[i];
    for(int i=0;i<V;i++){
        for(int j=0;j<V;j++){
            cost[i][j]=cost[i][j]=inf;
        }
    }
    for(int i=0;i<M;i++){
        int a,b,c;
        cin>>a>>b>>c;
        cost[a][b]=cost[b][a]=c;
    }
    dijkstra(S);
    printf("%d %d
",pathnum[D],toval[D]);
    vector<int>path=get_path(D);
    for(int i=0;i<path.size();i++){
        printf("%d%c",path[i],i==path.size()-1?'
':' ');
    }
    return 0;
}
原文地址:https://www.cnblogs.com/elpsycongroo/p/8512203.html