zoj3261:倒序并查集
zoj3261
题解:建议大家先做一下HDU4496,也是倒序并查集
找最大值和最大编号其实也比较简单,代码里Union有,大家应该能看懂。
其它都是一些细节上的处理
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>
#include <iostream>
using namespace std;
typedef pair<int,int>pii;
int const N = 10000 + 10;
int n,m,x,y,Q;
int p[N],fa[N],sum[N],num[N],ans[5*N];
pii c[2*N];
struct Query
{
string s;
int a,b;
}q[5*N];
set<pii>st;
void Init(){
st.clear();
for(int i=0;i<=n-1;i++) fa[i] = i,num[i] = i;
for(int i=0;i<=n-1;i++){ //每个星星的能量
scanf("%d",&p[i]);
sum[i] = p[i];
}
scanf("%d",&m);
for(int i=0;i<m;i++){ //相连的星星
scanf("%d%d",&x,&y);
st.insert(make_pair(min(x,y),max(x,y))); //这里一定要注意统一!!
}
scanf("%d",&Q);
for(int i=0;i<Q;i++){ //询问
cin>>q[i].s;
if(q[i].s[0] == 'q') cin>>q[i].a;
else{
scanf("%d%d",&q[i].a,&q[i].b);
st.erase(make_pair(min(q[i].a,q[i].b),max(q[i].a,q[i].b)));
}
}
}
int find(int x){
return x == fa[x] ? x : (fa[x] = find(fa[x]));
}
void Union(int x,int y){
int fx = find(x), fy = find(y);
if(fx != fy){
fa[fx] = fy;
if(sum[fy] < sum[fx]){
sum[fy] = sum[fx];
num[fy] = num[fx];
}else if(sum[fy] == sum[fx]){
if(num[fx] < num[fy])
num[fy] = num[fx];
}
}
}
int main(){
bool first = true;
while(~scanf("%d",&n)){
if(first) first = false;
else printf("\n");
Init();
for(set<pii>::iterator it=st.begin();it!=st.end();it++)
Union(it->first,it->second);
for(int i=Q-1;i>=0;i--){
if(q[i].s[0] == 'q'){
int u = find(q[i].a);
if(sum[u] <= p[q[i].a]) ans[i] = -1;
else ans[i] = num[u];
}else{
Union(q[i].a,q[i].b);
}
}
for(int i=0;i<Q;i++)
if(q[i].s[0] == 'q') printf("%d\n",ans[i]);
}
return 0;
}

浙公网安备 33010602011771号