P8047 [COCI2015-2016#4] GALAKSIJA 题解
考虑倒着做,将删边变成加边,用并查集启发式合并维护并且在合并时更新贡献。
考虑现在有两个集合
把
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
struct Node
{
int u, v, w;
Node(int u, int v, int w): u(u), v(v), w(w){}
Node() = default;
};
vector<Node> v;
int p[N];
int n;
long long ans = 0LL;
long long res[N];
int dis[N];
vector<pair<int, int>> G[N];
void dfs(int u, int f, int w)
{
dis[u] = dis[f] ^ w;
for (auto &[j, v] : G[u])
{
if (j ^ f) dfs(j, u, v);
}
}
class Union_Find
{
public:
int fa[N], sz[N];
map<pair<int, int>, int> mp;
vector<int> total[N];
void Init()
{
for (int i = 0; i < N; i++)
{
fa[i] = i, sz[i] = 1;
if (i >= 1 && i <= n) mp[make_pair(i, dis[i])]++, total[i].emplace_back(i);
}
}
int find(int u)
{
return (fa[u] == u ? u : fa[u] = find(fa[u]));
}
void merge(int u, int v)
{
if ((u = find(u)) == (v = find(v))) return;
if (sz[u] < sz[v]) swap(u, v);
fa[v] = u;
sz[u] += sz[v];
for (auto &j : total[v])
{
total[u].emplace_back(j);
ans += (mp.count(make_pair(u, dis[j])) ? mp[make_pair(u, dis[j])] : 0);
}
for (auto &j : total[v])
{
mp[make_pair(u, dis[j])]++;
mp.erase(make_pair(j, dis[j]));
}
total[v].clear();
total[v].shrink_to_fit();
}
}uf;
int main()
{
ios::sync_with_stdio(0), cin.tie(0);
cin >> n;
for (int i = 1; i < n; i++)
{
Node g;
cin >> g.u >> g.v >> g.w;
v.emplace_back(g);
G[g.u].emplace_back(make_pair(g.v, g.w));
G[g.v].emplace_back(make_pair(g.u, g.w));
}
for (int i = 1; i < n; i++)
{
cin >> p[i];
}
dfs(1, 1, 0);
uf.Init();
for (int i = n - 1; i >= 1; i--)
{
uf.merge(v[p[i] - 1].u, v[p[i] - 1].v);
res[i] = ans;
}
for (int i = 1; i < n; i++)
{
cout << res[i] << "\n";
}
cout << "0\n";
return 0;
}
分类:
题解
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通