zoj3261 Connections in Galaxy War---并查集灵活应用
题目链接:https://vjudge.net/problem/ZOJ-3261#author=87hbteo
题意:这个链接里说的挺清楚(然而原题面废话真多)
这题有一个类似的:就是洛谷P1197 https://www.cnblogs.com/edmunds/p/12752166.html 所以逆向处理应该没什么好说的。找目标星球的过程一开始想暴力,但那样显然就T了。其实可以把合并改写一下(见代码中的unite),这样可以保证每次找到的都是power最大,序号最小的星球
#include<bits/stdc++.h>
#define mp make_pair
using namespace std;
struct record{int t,u,v;}r[50010];
struct edge{int u,v;}e[20010];
int n,m,i,j,q,f,p[10010],par[10010],ans[50010];
map<pair<int,int>,int> d; //*
int find(int x){return par[x]==x?x:par[x]=find(par[x]);}
void unite(int u,int v){ //*
int fu=find(u);int fv=find(v);
if (fu==fv) return;
if (p[fu]<p[fv]) par[fu]=fv;
else if (p[fv]<p[fu]) par[fv]=fu;
else{
if (fu<fv) par[fv]=fu;
else par[fu]=fv;
}
}
int main(){
while (~scanf("%d",&n)){
d.clear();
for (i=0;i<n;i++) {
scanf("%d",&p[i]); par[i]=i;
}
scanf("%d",&m);
for (i=1;i<=m;i++) scanf("%d%d",&e[i].u,&e[i].v);
scanf("%d",&q);
for (i=1;i<=q;i++){
string s; cin>>s;
if (s=="query"){
r[i].t=1; scanf("%d",&r[i].u);
}
else{
r[i].t=0; scanf("%d%d",&r[i].u,&r[i].v);
d[mp(r[i].u,r[i].v)]=d[mp(r[i].v,r[i].u)]=1;
}
}
for (i=1;i<=m;i++)
if (d[mp(e[i].u,e[i].v)]==0&&d[mp(e[i].v,e[i].v)]==0)
unite(e[i].u,e[i].v);
int cnt=0;
for (i=q;i>=1;i--){
if (r[i].t==0) unite(r[i].u,r[i].v);
else{
cnt++;
int k=find(r[i].u);
if (p[k]>p[r[i].u]) ans[cnt]=k; else ans[cnt]=-1;
}
}
if (f==1) cout<<endl; f=1;
for (i=cnt;i>=1;i--) cout<<ans[i]<<endl;
}
return 0;
}

浙公网安备 33010602011771号