香甜的黄油(堆优化版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)。

浙公网安备 33010602011771号