题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3261
题意:N个星球,编号从0到N-1。每个星球有一个战斗力power,且这N个星球之间建有一些通道,可以相互联系,在星球大战中,一些星球的power不够强,要向和自己联通的星球中power最强的星球求救,且在星球大战中会有一些通道被损坏。然后有一些问题:destroy a b :a和b之间的通道被损坏。 query a:问a星球该向谁求救。
分析:并查集。如果一开始将星球大战之前建立的通道Union起来,以最大power的节点作为根节点,并按顺序读入数据,当遇到 query a时,就直接输出,但遇到destroy a b时,就不能简单的删掉a和b之间的边了,那么根节点的最大power值就无法维护。但如果我们先输入所有数据,即所谓的离线输入,将星球大战之后的状态作为初始状态,进行并查集的操作,遇到destroy时,就恢复a到b之间的通道,那么就很容易维护根节点的性质了,那么这题就变得很简单了。
Code:
#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <vector>
#include <queue>
#include <cmath>
#include <map>
#include <set>
#define eps 1e-8
#define LL long long
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=10005;
const int HASH=10000;
int f[maxn],power[maxn],ans[maxn*5];
struct node{
int u,v;
}tun[maxn<<1];
struct Node{
int a,b;
char cmd[10];
}query[maxn*5];
map<int,bool>mp;
int n,m,Q;
void make_set(){
for(int i=0;i<n;i++) f[i]=i;
}
int find_set(int x){
if(x!=f[x]){
f[x]=find_set(f[x]);
}
return f[x];
}
void Union(int x,int y){
int fx=find_set(x);
int fy=find_set(y);
if(fx!=fy){
if(power[fx]>power[fy]) f[fy]=fx;
else if(power[fx]<power[fy]) f[fx]=fy;
else {
if(fx<fy) f[fy]=fx;
else f[fx]=fy;
}
}
}
int main()
{
bool first=true;
while(scanf("%d",&n)!=EOF){
for(int i=0;i<n;i++) scanf("%d",&power[i]);
scanf("%d",&m);
for(int i=0;i<m;i++){
scanf("%d %d",&tun[i].u,&tun[i].v);
if(tun[i].u>tun[i].v) swap(tun[i].u,tun[i].v);
}
mp.clear();
scanf("%d",&Q);
for(int i=0;i<Q;i++){
scanf("%s",query[i].cmd);
if(query[i].cmd[0]=='q') scanf("%d",&query[i].a);
else {
scanf("%d %d",&query[i].a,&query[i].b);
if(query[i].a>query[i].b) swap(query[i].a,query[i].b);
mp[query[i].a*HASH+query[i].b]=true;
}
}
make_set();
for(int i=0;i<m;i++){
if(!mp[tun[i].u*HASH+tun[i].v]) Union(tun[i].u,tun[i].v);
}
int cnt=0;
for(int i=Q-1;i>=0;i--){
if(query[i].cmd[0]=='q') {
int fa=find_set(query[i].a);
if(power[fa]>power[query[i].a]) ans[cnt++]=fa;
else ans[cnt++]=-1;
}
else Union(query[i].a,query[i].b);
}
if(first) first=false;
else printf("\n");
for(int i=cnt-1;i>=0;i--)
printf("%d\n",ans[i]);
}
return 0;
}