描述
A 国有 n 个城市,第 i 个城市有 ai 个会议代表,这 n 个城市通过 n-1 条双向的高速公路连接,保证每两个城市都可以通过高速公路互相到达,每个人通过一条高速公路都要付相应的费用。
现在 A 国的总统想挑选一个城市作为会议中心,要求全国所有会议代表都到这个城市来,为了方便大家出行,A 国的总统可以让不超过 k 条高速公路的收费变为 0 。
现在你要安排挑选的城市和免费的高速公路,最小化的所有会议代表的路费总和。
输入
第一行两个整数 n, k
第二行 n 个非负整数,第 i 个表示ai
接下来 n-1 行,每行三个整数 u, v, w,描述一条收费为 w 的高速公路 (u, v)
1 ≤ n ≤ 10^3
0 ≤ k ≤ n-1
1 ≤ w, ai≤ 10^5
输出
输出最小的路费总和
样例解释
让 (2,3) 免费,然后选 2 作为会议城市
扫描二维码关注公众号,回复:
2450086 查看本文章
样例输入
3 1
1 2 3
1 2 1
2 3 2
样例输出
1
思路:
要求每个城市的代表到一个城市开会,相当于从图中某个点开始把图遍历一遍,在dfs的过程中记录走过的节点以及节点的人数然后再乘以边权。然后枚举每个点为起点,遍历图,然后删去k条收费最高的边,取一个最小值就是答案。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
const int maxn = 1e3+5;
struct edge
{
int to;
long long w;
};
long long e[maxn];
bool visit[maxn];
int A[maxn];
int f[maxn];
vector<edge>E[maxn];
int n,k;
void dfs(int x , long long w)
{
visit[x] = true;
for (int i = 0; i < E[x].size(); ++i) {
int y = E[x][i].to;
if (visit[y]) continue;
dfs(y,E[x][i].w);
f[x] += f[y];
}
f[x] += A[x];
e[x] = w * f[x];
}
long long solve(int x)
{
memset(f,0,sizeof(f));
memset(visit,0,sizeof(visit));
memset(e,0,sizeof(e));
dfs(x,0);
swap(e[x],e[n]);
sort(e+1,e+n);
long long res = 0;
for (int i = n-k-1; i >= 1; --i) {
res += e[i];
}
return res;
}
int main()
{
cin >> n >> k;
for (int i = 1; i <= n; ++i)
cin >> A[i];
int u,v;
long long w;
for (int i = 0; i < n-1; ++i) {
cin >> u >> v >> w;
edge tmp;
tmp.to = v;
tmp.w = w;
E[u].push_back(tmp);
tmp.to = u;
E[v].push_back(tmp);
}
long long res = 1e18;
for (int i = 1; i <= n; ++i)
res = min(res,solve(i));
cout << res << endl;
return 0;
}