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; }