pat grade A 1087 multi-standard dijkstra

First use map to solve the mapping of city names to numbers.
The title gives three criteria for judging the optimal path: The
first criterion: the minimum accumulation of edge weights.
The second criterion: the maximum accumulation of point weights.
The third criterion: the average point weight is the largest.
The following is to judge whether these three criteria can be processed by the dijkstra algorithm,
criterion 1:
S -> PATH1 -> B -> D is known to be the optimal first criterion, and it is proved that S -> PATH1 -> B is also optimal.
Assuming that S -> PATH2 -> B is shorter than it, then S -> PATH2 -> B -> D is shorter than the known shortest path. There is
a contradiction, so it does not exist. It is proved.

Criterion 2: The same reasoning can be proved.

Criterion 3: It is known that S -> PATH1 -> B -> D is the optimal third criterion, and it is proved that S -> PATH1 -> B is also optimal.
The number of points on PATH1 is N1, and the point weight is accumulated as W1
. The number of points on PATH2 is N2, and the point weight is accumulated as W2.
Then the average point weight of the known optimal path to D is (WS+W1+WB+WD) /(N1+3)
to the average point weight of B (WS+W1+WB)/(N1+2)
Suppose there is S -> PATH2 -> B is better than it, namely
(WS+W2+WB)/(N2 +2)> (WS+W1+WB)/(N1+2)
Proof: (WS+W2+WB+WD)/(N2+3)> (WS+W1+WB+WD)/(N1+3)
//To be continued
Insert picture description here
Criteria 3 is temporarily unprovable. The safe strategy is to use dijkstra to process the first two criteria, find multiple paths, and finally DFS finds the optimal path of the third criterion. If all three standards are dijkstra together, the pat test point can also pass, but the data may not be comprehensive.

#include <iostream>
#include <climits>
#include <string>
#include <vector>
#include <map>
#include <algorithm>

using namespace std;

const int maxv = 200;
const int INF = INT_MAX;

int N, K, S, D, mark=-1;
int v_weight[maxv];
int graph[maxv][maxv]={
    
    };
int d[maxv]; //第一标准:边权累积最小
bool confirmed[maxv]={
    
    };
int path_count[maxv]={
    
    }; //路径条数
int v_w_sum[maxv]={
    
    }; //第二标准:点权累积最大
vector<int> pre[maxv];
map<string, int> mp;

int f_ave=0;
vector<int> path, t_path;

int change(string a); //城市名到编号互转
void init(int s);
void dijkstra(int s); //以s为起点
void DFS(int v, int n); //访问到v,已经累积点权sum,点数n

int main(){
    
    
    string start;
    cin>>N>>K>>start;
    S = change(start); //起点
    v_weight[S]=0;
    for(int i=0; i<N-1; i++){
    
    
        string city;
        int w;
        cin>>city>>w;
        int c = change(city);
        v_weight[c] = w;
        if(city=="ROM") D = c; //终点
    }
    while(K--){
    
    
        string city1, city2;
        int cost;
        cin>>city1>>city2>>cost;
        int c1 = change(city1);
        int c2 = change(city2);
        graph[c1][c2] = graph[c2][c1] = cost;
    }
    dijkstra(S); //以第一、二标准找到最优路径
    DFS(D, 0); //在pre形成的倒置图上深度优先遍历,找第三标准最优
    cout<<path_count[D]<<' '<<d[D]<<' '<<v_w_sum[D]<<' '<<f_ave<<endl;
    int nm = path.size();
    for(int i=nm-1; i>=0; i--){
    
    
        map<string, int>::iterator it;
        for(it=mp.begin(); it!=mp.end(); it++){
    
    
            if(it->second==path[i]) break;
        }
        cout<<it->first;
        if(i>0) cout<<"->";
    }

    return 0;
}

int change(string a){
    
    
    map<string, int>::iterator it = mp.find(a);
    if(it!=mp.end()) return it->second;
    else{
    
    
        mark++;
        mp.insert(make_pair(a, mark));
        return mark;
    }
}

void init(int s){
    
    
    fill(d, d+N, INF);
    d[s] = 0;
    path_count[s] = 1;
    v_w_sum[s] = v_weight[s];
    return;
}

void dijkstra(int s){
    
    
    init(s);
    for(int k=0; k<N; k++){
    
    
        int u=-1, min_d=INF;
        for(int i=0; i<N; i++){
    
    
            if(!confirmed[i] && d[i]<min_d){
    
    
                u = i;
                min_d = d[i];
            }
        }
        if(u==-1) return;
        confirmed[u] = true;
        for(int j=0; j<N; j++){
    
    
            //u->j
            if(!confirmed[j] && graph[u][j]!=0){
    
    
                if(d[u]+graph[u][j]<d[j]){
    
    
                    //第一标准更优,要换路径
                    d[j] = d[u] + graph[u][j];
                    v_w_sum[j] = v_w_sum[u] + v_weight[j];
                    path_count[j] = path_count[u];
                    pre[j].clear();
                    pre[j].push_back(u);
                }
                else if(d[u]+graph[u][j]==d[j]){
    
    
                    path_count[j] += path_count[u];
                    if(v_w_sum[u]+v_weight[j]>v_w_sum[j]){
    
    
                        //第一标准相同,第二标准更优,要换路径,即清空pre再添加
                        v_w_sum[j] = v_w_sum[u] + v_weight[j];
                        pre[j].clear();
                        pre[j].push_back(u);
                    }
                    else if(v_w_sum[u]+v_weight[j]==v_w_sum[j]){
    
    
                        //一、二标准都相同,直接添加
                        pre[j].push_back(u);
                    }
                    //如果第一标准相同,第二标准更差,则路径更差,不记录
                }
                //如果第一标准更差,则路径更差,不记录
            }
        }
    }
    return;
}

void DFS(int v, int n){
    
    
    t_path.push_back(v);
    if(v==S){
    
    
        int a = v_w_sum[D]/n;
        if(a>f_ave){
    
    
            f_ave = a;
            path = t_path;
        }
        t_path.pop_back();
        return;
    }
    int t = pre[v].size();
    for(int i=0; i<t; i++){
    
    
        DFS(pre[v][i], n+1);
    }
    t_path.pop_back();
    return;
}

Guess you like

Origin blog.csdn.net/sinat_37517996/article/details/104545500