树上删除点
给定一张n个点 m条边的无向图,点有点权。需要进行n次操作,每次操作,选择一个点a,并移除该点以及与该点相连的所有边,其代价是与点a直接相连的所有点权和。问所有操作的代价的最大值的最小值是多少。
暴力 + 根堆
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
int main(void) {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
int n, m;
cin >> n >> m;
vector<LL> a(n);
for(auto &i : a)
cin >> i;
vector<vector<int>> edge(n, vector<int>());
vector<LL> sum(n, 0);
for(int i = 1; i <= m; ++ i){
int x, y;
cin >> x >> y;
-- x;
-- y;
edge[x].push_back(y);
edge[y].push_back(x);
sum[x] += a[y];//sum表示删除这个点需要的价值
sum[y] += a[x];
}
priority_queue<pair<LL, int>> qwq;
for(int i = 0; i < n; ++ i){
qwq.push({- sum[i], i});
}
LL ans = 0;
int cnt = n;
set<int> ff;
while(cnt){//不再以根堆的点作为点
auto [val, u] = qwq.top();
val = -val;
qwq.pop();
if (val != sum[u])
continue;
ff.insert(u);//插入这个点 表示这个点已经被删除了
ans = max(ans, val);
cnt --;
for(auto &v : edge[u]){
if (ff.find(v) != ff.end())//删除过的点不再处理
continue;
sum[v] -= a[u];//连接他的点的价值都减少
qwq.push({-sum[v], v});//存负值因为默认大根堆取出来在变符号 就变最小值
}
}
cout << ans << '\n';
return 0;
}