rt,思路是 mrsrz 老师题解里的思路。
调了将近 4h,始终过不去,把 AC 代码贺过来对拍,发现答案始终大一点。
后来确定,是块内暴力合并出了问题,但是我始终觉得我的代码和 srz 老师的代码本质相同。
我的想法是直接讨论这条边的修改时间在询问前还是询问后,srz 老师的代码里大概是把被修改的边拆成了修改前和修改后拆成两部分进行覆盖。感觉好像没有区别,但我的代码确实是错的。求教 /kk。
出错误的位置在代码里注释标出。照着 srz 老师的思路改的正确代码。
#include <bits/stdc++.h>
#define fir first
#define sec second
#define pb emplace_back
using i64 = long long;
using tpi = std::tuple<int, int, int>;
using pii = std::pair<int, int>;
const int maxn = 1e5 + 5;
int n, m, q, s, t, id[maxn];
struct edge {
int u, v, w, id;
edge() {
u = v = w = id = 0;
}
edge(int u, int v, int w, int id) : u(u), v(v), w(w), id(id) {}
} E[maxn];
int pre[maxn], sz[maxn], tp, ans[maxn];
pii stk[maxn];
int find(int x) {
while(x != pre[x])
x = pre[x];
return x;
}
void merge(int x, int y) {
x = find(x);
y = find(y);
if(x == y)
return ;
if(sz[x] > sz[y])
std::swap(x, y);
pre[x] = y;
sz[y] += sz[x];
stk[++ tp] = (pii){x, y};
return ;
}
void recall(int lst) {
while(tp > lst) {
int x = stk[tp].fir, y = stk[tp].sec;
pre[x] = x;
sz[y] -= sz[x];
-- tp;
}
return ;
}
std::vector<std::tuple<int, int, int>> M, Q;
bool vis[maxn];
void solve() {
std::sort(E + 1, E + 1 + m, [&](const edge& lhs, const edge& rhs) {
return lhs.w > rhs.w;
});
for(int i = 1;i <= m;++ i)
id[E[i].id] = i;
std::sort(Q.begin(), Q.end(), [&](const tpi& lhs, const tpi& rhs) {
return std::get<2> (lhs) > std::get<2> (rhs);
});
tp = 0;
for(int i = 1;i <= n;++ i)
pre[i] = i, sz[i] = 1;
for(auto& p : M)
vis[id[std::get<1> (p)]] = true;
for(int i = 1, j = 0;j < (int)Q.size();++ j) {
int tim, x, y;
std::tie(tim, x, y) = Q[j];
while(i <= m&&E[i].w >= y) {
if(!vis[i])
merge(E[i].u, E[i].v);
++ i;
}
int lst = tp;
for(auto& p : M) {
int t, e, val;
std::tie(t, e, val) = p;
// 就是这里的讨论,不理解为什么是错的。
if(t <= tim) {
if(val >= y)
merge(E[id[e]].u, E[id[e]].v);
}
else if(E[id[e]].w >= y)
merge(E[id[e]].u, E[id[e]].v);
//
}
ans[tim] = sz[find(x)];
recall(lst);
}
for(auto& p : M) {
int x, y, z;
std::tie(x, y, z) = p;
E[id[y]].w = z;
vis[id[y]] = false;
}
Q.clear();
M.clear();
return ;
}
int main() {
scanf("%d %d", &n, &m);
for(int i = 1;i <= m;++ i)
scanf("%d %d %d", &E[i].u, &E[i].v, &E[i].w), E[i].id = i;
scanf("%d", &q);
s = 1024;
for(int k = 1;k <= q;++ k) {
int op, u, v;
scanf("%d %d %d", &op, &u, &v);
if(op == 1)
M.pb(k, u, v);
else
Q.pb(k, u, v);
if(k % s == 0||k == q)
solve();
}
for(int i = 1;i <= q;++ i)
if(ans[i])
printf("%d\n", ans[i]);
return 0;
}