并查集撤消操作
https://www.cnblogs.com/y2823774827y/p/11600426.html
int parent[maxn],siz[maxn]; //按秩合并用siz,siz小的连向siz大的
vector<pii> tmp; //记录上次合并用到的节点
int find(int p) //递归找根节点,注意没有路径压缩
{
if( p == parent[p] ) return p;
return find(parent[p]);
}
void done(pii v) //合并两个点
{
int x = find(v.fi),y = find(v.se);
if( x == y )
{
tmp.push_back(mp(-1,-1)); //已经在同一集合中,不用再连了
continue;
}
if( siz[x] > siz[y] )
swap(x,y); //一定是小的连向大的
tmp.push_back(mp(x,y)); //把信息存入栈中
parent[x] = y; //合并一下
siz[y] += siz[x];
}
void undone() //反悔操作
{
pii z = tmp.back(); //取出栈顶元素
tmp.pop_back();
if( z.fi == -1 )
continue; //那时候没有操作,那么也不需要回退
parent[z.fi] = z.fi;
//直接回退,做了啥就别做啥
siz[z.se] -= siz[z.fi];
}
#include<bits/stdc++.h>
#define LL long long
using namespace std;
typedef pair<int, int> PII;
struct node{
int x, y, z;
}e[500010];
struct query{
int x, y, id;
friend bool operator < (const query &a, const query &b){
return a.id<b.id;
}
};
int father[500010], ret[500010], n, m, qu;
stack<PII > s;
vector<query> v[500010];
vector<PII > g[500010];
int fd(int x){
if(father[x]<0){
return x;
}
else{
return fd(father[x]);
}
}
void work(int x, int y)
{
int fx=fd(x), fy=fd(y);
if(fx==fy){
return ;
}
if(father[fx]<=father[fy])
{
father[fx]+=father[fy];
father[fy]=fx;
}
else
{
father[fy]+=father[fx];
father[fx]=y;
}
}
void solve(int cnt, int x, int y)
{
while(!s.empty()){
s.pop();
}
for (int i=x; i<=y; ++i)
{
int fx=fd(v[cnt][i].x), fy=fd(v[cnt][i].y);
if(fx==fy){//如果有一条边添加不进去就不可以
ret[v[cnt][i].id]=1;
}
else if(father[fx]<=father[fy]){
s.push(make_pair(fy, father[fy]));
father[fy]=fx;
}
else{
s.push(make_pair(fx, father[fx]));
father[fx]=fy;
}
}
while(!s.empty())
{
father[s.top().first] = s.top().second;
s.pop();
}
}
int main(){
memset(father, -1, sizeof(father));
scanf("%d%d", &n, &m);
for(int i=1; i<=m; i++){
scanf("%d%d%d", &e[i].x, &e[i].y, &e[i].z);
g[e[i].z].push_back(make_pair(e[i].x, e[i].y));
//按权值 保存原始边
}
scanf("%d", &qu);
for(int i=1; i<=qu; i++)
{
int opnum;
scanf("%d", &opnum);
for(int j=1; j<=opnum; j++)
{
int x;
scanf("%d", &x);
v[e[x].z].push_back({e[x].x, e[x].y, i});
//按权值 保存所有的查询的边
}
}
for(int i=1; i<=500000; i++)
{
sort(v[i].begin(), v[i].end());
}
for(int i=1; i<=500000; i++)
{
for(int j=0; j<g[i-1].size(); j++)
{//把权值<i的全部添加进去。形成的每个连通块包含的点集是一样的
work(g[i-1][j].first, g[i-1][j].second);
}
int sz=v[i].size();
if(sz==0)
{
continue;
}
int now=0;
while(now<sz)
{
int j=now;
while(j+1<sz&&v[i][j+1].id==v[i][j].id){
//找到把属于同一个询问的所有的边区间
j++;
}
solve(i, now, j);//判断这个区间
now=j+1;
}
}
for(int i=1; i<=qu; i++)
{
printf("%s\n", ret[i]?"NO":"YES");
}
return 0;
}
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int MAXN = 5e5 + 5;
struct edge {
int from, to, dist;
};
int n, m, q, cnt;
int fa_1[MAXN], fa_2[MAXN], kase[MAXN];
bool wa[MAXN];
edge e[MAXN];
vector<int> gra[MAXN];
vector<pair<int, int> > qr[MAXN];
int findfather_1(int x)
{
return (fa_1[x] == x ? x : fa_1[x] = findfather_1(fa_1[x]));
}
int findfather_2(int x)
{
if (kase[x] != cnt)
{
kase[x] = cnt;
fa_2[x] = findfather_1(x);
}
return (x == fa_2[x] ? x : fa_2[x] = findfather_2(fa_2[x]));
}
int main()
{
scanf("%d %d", &n, &m);
int a, b, c, mx = 0;
for (int i = 1; i <= m; i++) {
scanf("%d %d %d", &a, &b, &c);
e[i].from = a;
e[i].to = b;
e[i].dist = c;
gra[c].push_back(i);
mx = max(mx, c);
}
int k, x;
scanf("%d", &q);
for (int i = 1; i <= q; i++)
{
scanf("%d", &k);
for (int j = 1; j <= k; j++)
{
scanf("%d", &x);
qr[e[x].dist].push_back(make_pair(i, x));
}
}
memset(wa, false, sizeof(wa));
memset(kase, 0, sizeof(kase));
for (int i = 1; i <= n; i++) fa_1[i] = i;
cnt = 0;
for (int i = 1; i <= mx; i++)
{
sort(qr[i].begin(), qr[i].end());
for (int j = 0; j < qr[i].size(); j++)
{
if (j == 0 || qr[i][j].first != qr[i][j - 1].first)
cnt++;
int x = findfather_2(e[qr[i][j].second].from);
int y = findfather_2(e[qr[i][j].second].to);
if (x == y) wa[qr[i][j].first] = true;
fa_2[y] = x;
}
for (int j = 0; j < gra[i].size(); j++) {
int x = findfather_1(e[gra[i][j]].from);
int y = findfather_1(e[gra[i][j]].to);
fa_1[y] = x;
}
}
for (int i = 1; i <= q; i++)
printf(!wa[i] ? "YES\n" : "NO\n");
return 0;
}
//https://blog.csdn.net/Shili_Xu/article/details/78726516

浙公网安备 33010602011771号