您的位置:首页 > 其它

zoj 3261 逆向并查集

2013-02-07 03:53 417 查看
很明显是逆向的并查集,建立边再销毁,思路也很巧妙的逆向思考~

如果正着一一销毁,相当于倒着一一建边。

所以保存Q次提问,最后倒着来一一建边。

在此之前先把没有销毁的边全部建好~细节power能量注意一下~

View Code

#include <map>
#include <stdio.h>
#include <string.h>
#include <vector>
#include <iostream>
using namespace std;

const int N=50005;
int n,m,i,j;
int power
;
int father
;
int g
[3];
int ans
,cnt;
map<pair<int,int>,int>M;

int find(int x){
if(x!=father[x]){
father[x]=find(father[x]);
}
return father[x];
}

void merge(int a,int b){
int x=find(a);
int y=find(b);
if(x==y) return ;
if(power[x]>power[y]||(power[x]==power[y]&&x<y)) father[y]=x;
else father[x]=y;
}
int main(){
char ch[10];
int a,b,q,k=0;
while(scanf("%d",&n)!=EOF){
M.clear();
for(i=0;i<n;i++)
scanf("%d",&power[i]),
father[i]=i;

scanf("%d",&m);
for(i=0;i<m;i++){
scanf("%d%d",&a,&b);
if(a>b) a^=b^=a^=b;
M[make_pair(a,b)]=1;
}

scanf("%d",&q);
for(i=0;i<q;i++){
scanf("%s",ch);
if(ch[0]=='q'){
scanf("%d",&a);
g[i][0]=0;
g[i][1]=a;
}else{
scanf("%d%d",&a,&b);
g[i][0]=1;
g[i][1]=a;
g[i][2]=b;
if(a>b) a^=b^=a^=b;
M[make_pair(a,b)]=0;
}
}

map<pair<int,int>,int>::iterator it;
for(it=M.begin();it!=M.end();it++){
if(it->second){
pair<int,int> tmp=it->first;
merge(tmp.first,tmp.second);
}
}
cnt=0;
while(q--){
if(g[q][0]){
merge(g[q][1],g[q][2]);
}else{
a=g[q][1];
int x=find(a);
if(power[x]==power[a]) ans[cnt++]=-1;
else ans[cnt++]=x;
}
}
if(k++) puts("");
while(cnt--)
printf("%d\n",ans[cnt]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: