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;
}
posted @ 2023-01-08 23:56  Zeoy_kkk  阅读(31)  评论(0编辑  收藏  举报