CodeForces - 1213G Path Queries
CodeForces - 1213G Path Queries
题解:并查集+思维
现在给你由许多边组成的树,离线询问路径最大权重不超过\(w^i\)的路径数量
我们不一定要在树上找,我们可以通过他询问的\(w^i\),去一步步构建树,先按照边权排序,比如说w=1,我们就把所有权值为1的边构建出来,然后路径数量不就是\(C{_n^2}\)因为是离线查询,我们考虑将查询排序,我们先做权重小的,这样答案不用重复计算了
#include <bits/stdc++.h>
#define Zeoy std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0)
#define all(x) (x).begin(), (x).end()
#define endl '\n'
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-9;
const int N = 2e5 + 10;
int n, m;
int fa[N], szp[N];
void init()
{
for (int i = 1; i <= n; ++i)
fa[i] = i, szp[i] = 1;
}
int find(int x)
{
return x == fa[x] ? x : fa[x] = find(fa[x]);
}
void merge(int x, int y)
{
int fx = find(x);
int fy = find(y);
if (fx != fy)
{
fa[fx] = fy;
szp[fy] += szp[fx];
}
}
array<int, 3> a[2 * N];
ll ans[N];
int main(void)
{
Zeoy;
int t = 1;
// cin >> t;
while (t--)
{
cin >> n >> m;
init();
for (int i = 1, u, v, w; i <= n - 1; ++i)
{
cin >> u >> v >> w;
a[i] = {w, u, v};
}
for (int i = n, w; i <= m + n - 1; ++i)
{
cin >> w;
a[i] = {w, inf, i - n + 1}; //是有技巧的地方
}
sort(a + 1, a + n + m);
ll sum = 0;
for (int i = 1; i <= n + m - 1; ++i)
{
int u = a[i][1];
int v = a[i][2];
if (u != inf)
{
sum += (ll)szp[find(u)] * szp[find(v)];
merge(u, v);
}
else
{
ans[v] = sum;
}
}
for (int i = 1; i <= m; ++i)
cout << ans[i] << " ";
cout << endl;
}
return 0;
}