香甜的黄油(堆优化版dijkstra)

题目:香甜的黄油

题目链接:https://ac.nowcoder.com/acm/problem/22947

题意:有n只奶牛,p个牧场,每只奶牛都在一个牧场中(可能有奶牛在同个牧场)。确定一个集合的牧场,所有奶牛都到该牧场集合,要使得所有奶牛到该牧场的距离之和最短,求最短距离之和。

输入:第一行: 三个数:奶牛数N(1 <= N <= 800),牧场数(2<=P<=800),牧场间的无向边数C(1<=C<=1450)
    第二行到第N+1行: 1到N头奶牛所在的牧场号
    第N+2行到第N+C+1行: 每行有三个数:相连的牧场A、B,两牧场间距离D(1<=D<=255)。

输出:输出奶牛必须走的最小距离和。

样例输入:

3 4 5

2

3

4

1 2 1

1 3 5

2 3 7

2 4 3

3 4 5

样例输出:

8

样例解释:所有奶牛都到牧场4集合,则奶牛1走3,奶牛2走5,奶牛3走0,总共走8。可以确定,当所有奶牛在牧场4集合时,所有奶牛走的距离和最短。

题目分析:dijkstra求最短路。

解题步骤:枚举所有奶牛在各个牧场集合的情况,则需要枚举p(牧场数)次,每次使用堆优化版dijkstra算法求各个牧场到 集合的牧场的最短距离,然后返回所有奶牛到 集合的牧场的最短距离之和,取最小值即可。

AC代码:

#include<iostream>

#include<vector>

#include<queue>

 

using namespace std;

const int N = 810, P = 810;

int a[N], dis[P], n, p, m, inf = 1e9;

struct st{

           int x, y;

           bool operator < (const st &X) const{

              return y > X.y;

           }

};

vector<st> v[N];

 

int dij(int u){

           for(int i = 1;i <= p;i++) dis[i] = inf;

           dis[u] = 0;

          

           priority_queue<st> pq;

           pq.push({u, dis[u]});

          

           while(!pq.empty()){

              int x = pq.top().x;

              pq.pop();

             

              for(int i = 0;i < v[x].size();i++){

                     int t = v[x][i].x;

                     if(dis[t] > dis[x] + v[x][i].y){

                            dis[t] = dis[x] + v[x][i].y;

                            pq.push({t, dis[t]});

                     }

              }

           }

          

           int res = 0;

           for(int i = 1;i <= n;i++)    res += dis[a[i]];

           return res;

}

 

void solve(){

           scanf("%d %d %d", &n, &p, &m);

           for(int i = 1;i <= n;i++) scanf("%d", &a[i]);

           while(m--){

              int x, y, z;

              scanf("%d %d %d", &x, &y, &z);

              v[x].push_back({y, z});

              v[y].push_back({x, z});

           }

          

           int ans = 1e9;

           for(int i = 1;i <= p;i++) ans = min(ans, dij(i));

           printf("%d\n", ans);

}

 

int main(void){

           solve();

          

           return 0;

}

时间复杂度:O(P * ClogP),跑了P次最短路,每次时间复杂度为ClogP。

空间复杂度:O(N)。

posted @ 2021-10-16 22:11  思丶君  阅读(138)  评论(0)    收藏  举报