1087 All Roads Lead to Rome (30 分)(最短路径)

直接用Dijkstra做

#include<bits/stdc++.h>

using namespace std;
int n,m;
map<string,int>si;
map<int,string>is;
const int N=251;
int weight[N];
int mp[N][N];
const int inf=0x3f3f3f3f;
int dis[N];
bool vis[N];
int num[N];
int w[N];
int past[N];
int path[N];
void Dijkstra(int v)
{
    fill(vis,vis+N,false);
    fill(dis,dis+N,inf);
    fill(w,w+N,0);
    fill(num,num+N,0);
    fill(past,past+N,0);
    fill(path,path+N,0);
    //for(int i=0;i<=n-1;i++) dis[i]=mp[v][i];
    dis[v]=0;
    num[v]=1;
    for(int i=0;i<n;i++){
        int u=-1;
        int minn=inf;
        for(int j=0;j<n;j++){
            if(!vis[j]&&minn>dis[j]){
                u=j;
                minn=dis[j];
            }
        }
        if(u==-1) return;
        vis[u]=true;
        for(int j=0;j<n;j++){
            if(!vis[j]&&mp[u][j]!=inf){
                if(dis[j]>dis[u]+mp[u][j]){//第一标尺: 最短路径
                    dis[j]=dis[u]+mp[u][j];
                    num[j]=num[u];
                    w[j]=w[u]+weight[j];
                    past[j]=past[u]+1;//s->j顶点个数等于s->u顶点个数+1
                    path[j]=u;//更新路径
                }
                else if(dis[j]==dis[u]+mp[u][j]){
                    num[j]+=num[u];
                    if(w[u]+weight[j]>w[j]){//第二标尺:结点的值
                        w[j]=w[u]+weight[j];
                        past[j]=past[u]+1;
                        path[j]=u;
                    }
                    else if(w[u]+weight[j]==w[j]){
                        double uAvg=1.0*(w[u]+weight[j])/(past[u]+1);
                        double vAvg=1.0*w[j]/past[j];
                        if(uAvg>vAvg){//第三标尺:平均结点值
                            past[j]=past[u]+1;
                            path[j]=u;
                        }
                    }
                }
            }
        }
    }
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    fill(mp[0],mp[0]+N*N,inf);
    fill(weight,weight+N,0);
    cin>>n>>m;
    string t;
    cin>>t;
    si[t]=0;
    is[0]=t;
    for(int i=1;i<=n-1;i++){
        string temp;
        cin>>temp;
        cin>>weight[i];
        si[temp]=i;
        is[i]=temp;
    }
    for(int i=0;i<m;i++){
        string a,b;
        cin>>a>>b;
        int num;
        cin>>num;
        int a1=si[a];
        int b1=si[b];
        mp[a1][b1]=mp[b1][a1]=num;
    }
    Dijkstra(0);
    int rom=si["ROM"];
    cout<<num[rom]<<" "<<dis[rom]<<" "<<w[rom]<<" "<<w[rom]/past[rom]<<endl;
    int tt=rom;
    vector<int>vec;
    while(tt!=0){
        vec.push_back(tt);
        tt=path[tt];
    }
    reverse(vec.begin(),vec.end());
    cout<<t<<"->";
    for(int i=0;i<vec.size();i++){
        if(i) cout<<"->";
        cout<<is[vec[i]];
    }
    cout<<endl;
    return 0;
}

用Dijkstra + dfs

这样做会更好理解

#include<bits/stdc++.h>

using namespace std;
int n,m;
map<string,int>si;
map<int,string>is;
const int N=251;
int weight[N];
int mp[N][N];
const int inf=0x3f3f3f3f;
int dis[N];
bool vis[N];
vector<int>path[N];

void Dijkstra(int v)
{
    fill(vis,vis+N,false);
    fill(dis,dis+N,inf);
    for(int i=0;i<n;i++) dis[i]=mp[v][i];
    dis[v]=0;
    for(int i=0;i<n;i++){
        int u=-1;
        int minn=inf;
        for(int j=0;j<n;j++){
            if(!vis[j]&&minn>dis[j]){
                minn=dis[j];
                u=j;
            }
        }
        if(u==-1) return;
        vis[u]=true;
        for(int j=0;j<n;j++){
            if(!vis[j]&&mp[u][j]!=inf){
                if(dis[j]>mp[u][j]+dis[u]){
                    dis[j]=mp[u][j]+dis[u];
                    path[j].clear();
                    path[j].push_back(u);
                }
                else if(dis[j]==mp[u][j]+dis[u]){
                    path[j].push_back(u);
                }
            }
        }
    }
}
vector<int>t,tt;
int minDis=inf;
int maxValue=-1;
int sum=0;
int num=0;
void dfs(int v)
{
    if(v==0){
        sum++;
        t.push_back(v);
        int sumDis=0;
        int sumValue=0;
        sumValue=weight[t[t.size()-1]];
        for(int i=t.size()-2;i>=0;i--){
           // sumDis+=mp[t[i+1]][t[i]];
            sumValue+=weight[t[i]];
        }
        //注意这里不再需要管最短路径这个第一标尺 因为我们用Dijkstra求出来了
        // 这几条路径
        //的长度是一样的并且是都是最小的
        if(maxValue<sumValue){
            maxValue=sumValue;
            tt=t;
        }
        else if(sumValue==maxValue){
            double a=1.0*sumValue/tt.size();
            double b=1.0*maxValue/t.size();
            if(a<b){
                tt=t;
            }
        }

        t.pop_back();
        return;
    }
    t.push_back(v);
    for(int i=0;i<path[v].size();i++){
        dfs(path[v][i]);
    }
    t.pop_back();
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    fill(mp[0],mp[0]+N*N,inf);
    fill(weight,weight+N,0);
    cin>>n>>m;
    string t;
    cin>>t;
    si[t]=0;
    is[0]=t;
    for(int i=1;i<=n-1;i++){
        string temp;
        cin>>temp;
        cin>>weight[i];
        si[temp]=i;
        is[i]=temp;
    }
    for(int i=0;i<m;i++){
        string a,b;
        cin>>a>>b;
        int num;
        cin>>num;
        int a1=si[a];
        int b1=si[b];
        mp[a1][b1]=mp[b1][a1]=num;
    }
    Dijkstra(0);
    int rom=si["ROM"];
    dfs(rom);
    cout<<sum<<" "<<dis[rom]<<" "<<maxValue<<" "<<maxValue/(tt.size()-1)<<endl;
    reverse(tt.begin(),tt.end());
    for(int i=0;i<tt.size();i++){
        if(i) cout<<"->";
        cout<<is[tt[i]];
    }
    cout<<endl;
    return 0;
}
原文地址:https://www.cnblogs.com/chenchen-12/p/10133552.html