1003 Emergency (25 分)(求最短路径)

给出N个城市,m条无向边。每个城市中都有一定数目的救援小组,所有边的边权已知。现在给出起点和终点,求从起点到终点的最短路径条数及最短经上的救缓小组数目只和。如果有多条最短路径,则输出数目只和最大的

Dijkstra 做法

#include<bits/stdc++.h>
using namespace std;
int n,m,s,u;
const int N=1000;
const int inf=0x3f3f3f3f;
int mp[N][N];
int dis[N];
bool vis[N];
int value[N];
int num[N];
int w[N];
void Dijkstra()
{
    fill(vis,vis+N,false);
    fill(dis,dis+N,inf);
    fill(w,w+N,0);
    fill(num,num+N,0);
    num[s]=1;//赋值
    w[s]=value[s];//赋值
    for(int i=0;i<n;i++) dis[i]=mp[s][i];
    dis[s]=0;
    for(int i=0;i<n-1;i++){
        int u=-1;
        int minn=inf;
        for(int j=0;j<n;j++){
            if(!vis[j]&&dis[j]<minn){
                u=j;
                minn=dis[j];
            }
        }
        if(u==-1) return;
        vis[u]=true;
        for(int j=0;j<n;j++){
            if(!vis[j]&&dis[u]+mp[u][j]<=dis[j]){
                if(mp[u][j]+dis[u]<dis[j]){
                    dis[j]=mp[u][j]+dis[u];
                    num[j]=num[u];
                    w[j]=w[u]+value[j];
                }
                else{
                    num[j]+=num[u];
                    if(w[u]+value[j]>w[j]){
                        w[j]=w[u]+value[j];
                    }
                }
            }
        }

    }
}
int main()
{
    scanf("%d %d %d %d",&n,&m,&s,&u);
    for(int i=0;i<n;i++) scanf("%d",&value[i]);
    memset(mp,inf,sizeof(mp));
    while(m--){
        int a,b,c;
        scanf("%d %d %d",&a,&b,&c);
        mp[a][b]=mp[b][a]=c;
    }
    Dijkstra();
    printf("%d %d",num[u],w[u]);

    return 0;
}

spfa做法

#include<bits/stdc++.h>

using namespace std;
int n,m,s,v;
struct node
{
    int to;
    int dis;
    node(int _to=0,int _dis=0):to(_to),dis(_dis){}
};
const int N=1010;
int dis[N];
bool vis[N];
int w[N];
int num[N];
int value[N];
vector<node>mp[N];
set<int>st[N];
const int inf=0x3f3f3f3f;
void spfa()
{
    fill(dis,dis+N,inf);
    fill(vis,vis+N,false);
    fill(w,w+N,0);
    w[s]=value[s];
    num[s]=1;
    queue<int>Q;
    Q.push(s);
    vis[s]=true;
    dis[s]=0;
    while(!Q.empty()){
        int u=Q.front();
        Q.pop();
        vis[u]=false;
        for(int i=0;i<mp[u].size();i++){
            int to=mp[u][i].to;
            int diss=mp[u][i].dis;
            if(diss+dis[u]<dis[to]){
                dis[to]=diss+dis[u];
                w[to]=w[u]+value[to];
                num[to]=num[u];
                st[to].clear();
                st[to].insert(u);
                if(!vis[to]){
                    Q.push(to);
                    vis[to]=true;
                }
            }
            else if(diss+dis[u]==dis[to]){
                if(w[to]<w[u]+value[to]){
                    w[to]=w[u]+value[to];               
                }
                st[to].insert(u);
                num[to]=0;//因为spfa会重复到一个点 所以可能重复的边
                for(set<int>::iterator it=st[to].begin();it!=st[to].end();++it){
                    num[to]+=num[*it];
                }
                if(!vis[to]){
                    Q.push(to);
                    vis[to]=true;
                }
            }
        }
    }
}
int main()
{
    scanf("%d %d %d %d",&n,&m,&s,&v);
    for(int i=0;i<n;i++) scanf("%d",&value[i]);
    for(int i=0;i<n;i++) mp[i].clear();
    while(m--){
        int a,b,c;
        scanf("%d %d %d",&a,&b,&c);
        mp[a].push_back(node(b,c));
        mp[b].push_back(node(a,c));
    }
    spfa();
    printf("%d %d
",num[v],w[v]);

    return 0;
}
原文地址:https://www.cnblogs.com/chenchen-12/p/10084659.html