思路:
- “带权并查集”(权不变),离线删除、查询
- 离线:结构体存储。
- 将顺序的删除改为逆序的增添,起始图为全部摧毁后的图,再逆序输出答案。
- 还没有AC
代码:
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <stack>
using namespace std;
const int maxn = 10005;
int N,M,Q;
int par[maxn];
int val[maxn];
struct EDGE{
int l,r;
bool ok;
}edge[maxn * 2];
void ADDEDGE(int i,int l,int r){
edge[i].l = l;
edge[i].r = r;
edge[i].ok = true;
return ;
}
struct HANDLE{
int w;
int l,r;
HANDLE(int w,int l,int r) : w(w) , l(l) , r(r) {} ;
};
stack<HANDLE> S;
stack<int> s;
void INIT(){
memset(par , -1 , sizeof(par));
return ;
}
int FIND(int i){
return par[i] == -1 ? i : par[i] = FIND(par[i]);
}
void UNION(int l,int r){
int parl = FIND(l);
int parr = FIND(r);
if(parl != parr){
if(val[parl] > val[parr])
par[parr] = parl;
else if(val[parl] < val[parr])
par[parl] = parr;
else{
if(parl < parr)
par[parr] = parl;
else
par[parl] = parr;
}
}
return ;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
while(cin>>N){
INIT();
for(int i=0;i<N;i++)
scanf("%d" , val+i);
cin>>M;
for(int i=1;i<=M;i++){
int l,r;
scanf("%d%d" , &l , &r);
ADDEDGE(i,l,r);
}
cin>>Q;
for(int i=1;i<=Q;i++){
string str;
int l,r;
int w;
cin>>str;
if(str.size() == 5){
cin>>l;
w = 0;
r = -1;
}
else{
cin>>l>>r;
w = 1;
for(int i=1;i<=M;i++){
if((edge[i].l == l && edge[i].r == r) || (edge[i].r == l && edge[i].l == r)){
edge[i].ok = false;
break;
}
}
}
S.push(HANDLE(w,l,r));
}
for(int i=1;i<=M;i++)
if(edge[i].ok)
UNION(edge[i].l , edge[i].r);
while(S.size()){
HANDLE cur = S.top() ; S.pop() ;
if(!cur.w){
int ans = FIND(cur.l);
if(val[ans] == val[cur.l])
s.push(-1);
else
s.push(ans);
}
else
UNION(cur.l , cur.r);
}
while(s.size()){
cout<<s.top()<<endl;
s.pop();
}
}
return 0;
}