PAT A1087 All Roads Lead to Rome ——你不是真正的快乐

PAT A1087 All Roads Lead to Rome

  • dj里面的条款还是记不太清,反正是需要不断更新和比较的维度都要用数组去装
  • 增加新的维度以后,起点处的初始化也要增加相应的维度
  • 填充的值别搞错(0,INF,false,pre[i] = i)
  • 本题平均值的维度符合局部最优,对比自行车管理那道题
  • 路径条数是从1开始的,而顶点数是从0开始的,因为起点不happy,算均值时没有他
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <math.h>
#include <set>
#include <map>
#include <unordered_map>
#include <stack>


using namespace std;


#define MAXSIZE 233
#define INF 999999999

int G[MAXSIZE][MAXSIZE],weight[MAXSIZE],dist[MAXSIZE],pre[MAXSIZE],w[MAXSIZE],pnum[MAXSIZE],vnum[MAXSIZE];
bool visited[MAXSIZE] = {false};
int cnum,rnum;
string idx_to_name[MAXSIZE];
unordered_map<string,int> umap;
stack<string> stk;

void dj(int s){
    fill(dist,dist + MAXSIZE,INF);
    fill(visited,visited + MAXSIZE,false);
    for(int i = 0;i < cnum;i ++) pre[i] = i;
    dist[s] = 0;
    w[s] = weight[s];
    pnum[s] = 1;
    for(int i = 0;i < cnum;i ++){
        int u = -1,min = INF;
        for(int j = 0;j < cnum;j ++){
            if(!visited[j] && dist[j] < min){
                min = dist[j];
                u = j;
            }
        }
        if(u == -1) return;
        visited[u] = true;
        for(int v = 0;v < cnum;v ++){
            if(!visited[v] && G[u][v] != INF){
                if(dist[v] > dist[u] + G[u][v]){
                    dist[v] = dist[u] + G[u][v];
                    w[v] = w[u] + weight[v];
                    pre[v] = u;
                    pnum[v] = pnum[u];
                    vnum[v] = vnum[u] + 1;
                }else if(dist[v] == dist[u] + G[u][v]){
                    pnum[v] += pnum[u];
                    if(w[v] < w[u] + weight[v]){
                        w[v] = w[u] + weight[v];
                        pre[v] = u;
                        vnum[v] = vnum[u] + 1;
                    }else if(w[v] == w[u] + weight[v]){
                        double avg_wv = 1.0 * w[v] / vnum[v];
                        double avg_new = 1.0 * w[v] / (vnum[u] + 1);
                        if(avg_wv < avg_new){
                            pre[v] = u;
                            vnum[v] = vnum[u] + 1;
                        }
                    }
                }
            }
        }
    }
}


#define DEBUG 1



int main(){

#ifdef DEBUG
	freopen("1.txt","r",stdin);	
#endif

    string start;
    cin >> cnum >> rnum >> start;
    fill(G[0],G[0] + MAXSIZE * MAXSIZE,INF);
    umap[start] = 0;
    idx_to_name[0] = start;
    for(int i = 1;i < cnum;i ++){
        string name;
        cin >> name >> weight[i];
        umap[name] = i;
        idx_to_name[i] = name;
    }
    for(int i = 0;i < rnum;i ++){
        string n1,n2;
        int cost;
        cin >> n1 >> n2 >> cost;
        G[umap[n1]][umap[n2]] = G[umap[n2]][umap[n1]] = cost;
    }
    dj(umap[start]);
    int dst = umap["ROM"];
    cout << pnum[dst] << ' ' << dist[dst] << ' ' << w[dst] << ' ' << w[dst] / vnum[dst] << endl;
    int p = dst;
    do{
        stk.push(idx_to_name[p]);
        p = pre[p];
    }while(p != umap[start]);
    cout << start;
    while(!stk.empty()){
        cout << "->" << stk.top();
        stk.pop();
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值