PTA 首都选址(C++ Dijkstra)

该问题是一个图论问题,目标是找到一个城市作为新首都,使得它到所有其他城市的平均距离最短。通过Dijkstra算法计算每个城市的最短路径,然后选取平均距离最短且满足条件的城市。如果不存在这样的城市,则输出0。代码中包含了图的构建、最短路径计算和判断图是否为有向图的函数。
摘要由CSDN通过智能技术生成

某国准备选择新的首都,并对新首都的位置提出要求:即新首都到该国所有其他城市的平均距离最短(当然并不一定要求城市之间直达,间接道路也是允许的,但必须可达)。

已知该国的城市信息,请回答新首都应选择哪一个城市。

输入格式:

首先输入一个正整数T,表示测试数据的组数,然后是T组测试数据。每组测试数据第一行输入2个整数n和m,表示该国的城市总数以及现有的道路总数(1≤n≤100, 0≤m≤n*(n-1)/2 ),为方便起见,我们规定城市编号为1到n。
接下来输入m行数据,每行3个整数u、v、d(1≤u,v≤n,1≤d≤100),分别代表连接某条道路的两个城市编号以及该道路的长度。

输出格式:

对于每组测试,输出新首都的城市编号,若有多个满足条件的城市,选择编号最小的,若没有城市满足新首都的条件,请输出0。

输入样例:

3
4 5
1 2 10
1 3 20
4 3 5
4 1 7
2 4 8
3 1
1 2 10
5 7
1 2 2
3 2 5
2 5 18
4 2 6
1 3 8
3 4 11
1 4 8

输出样例:

4
0
2

 上代码,解析下次一定

#include<bits/stdc++.h>
using namespace std;
int t, n, m;
const int N = 105;
struct node{
    int id, dis;
    node(int a, int b){id = a, dis = b;}
    bool operator < (const node& u) const {return dis > u.dis;}
};
int g[N][N], dist[N];
bool done[N];
void begin();
bool isList();
int dijkstra(int s);
int main(){
    scanf("%d", &t);
    while(t--){
        memset(g, 0x3f, sizeof g);
        scanf("%d%d", &n, &m);
        while(m--){
            int u, v, d;
            scanf("%d%d%d", &u, &v, &d);
            g[u][v] = d;
        }
        begin();
        if(!isList()){
            printf("0\n");
            continue;
        }
        int mi = 0x3f3f3f3f, mi_i = 0;
        for(int i = 1; i <= n; ++i){
            int tmp = dijkstra(i);
            if(tmp < mi){
                mi = tmp;
                mi_i = i;
            }else if(tmp == mi && i < mi_i){
                mi_i = i;
            }
        }
        printf("%d\n", mi_i);
    }
    return 0;
}
int dijkstra(int s){
    memset(dist, 0x3f, sizeof dist);
    memset(done, 0, sizeof done);
    priority_queue<node> q;
    dist[s] = 0;
    q.emplace(node(s, dist[s]));
    while(!q.empty()){
        node u = q.top(); q.pop();
        if(done[u.id]) continue;
        done[u.id] = 1;
        for(int i = 1; i <= n; ++i){
            if(!done[i] && dist[i] > dist[u.id] + g[u.id][i]){
                dist[i] = dist[u.id] + g[u.id][i];
                q.emplace(node(i, dist[i]));
            }
        }
    }
    int sum = 0;
    for(int i = 1; i <= n; ++i){
        sum += dist[i];
    }
    return sum;
}
bool isList(){
    memset(done, 0, sizeof done);
    queue<int> q;
    q.push(1);
    while(!q.empty()){
        int s = q.front(); q.pop();
        if(done[s]) continue;
        done[s] = 1;
        for(int i = 1; i <= n; ++i){
            if(g[s][i] != 0x3f3f3f3f && !done[i])
                q.push(i);
        }
    }
    for(int i = 1; i <= n; ++i){
        if(!done[i]) return 0;
    }
    return 1;
}
void begin(){
    bool youxiang = 0;
    for(int i = 1; i <= n; ++i){
        for(int j = 1; j <= n; ++j){
            if(g[i][j] != 0x3f3f3f3f && g[j][i] != 0x3f3f3f3f){
                youxiang = 1;
                break;
            }
        }
        if(youxiang) break;
    }
    if(!youxiang){
        for(int i = 1; i <= n; ++i){
            for(int j = 1; j <= n; ++j){
                if(g[i][j] != 0x3f3f3f3f)
                    g[j][i] = g[i][j];
            }
        }
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值