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

  

原文地址:https://www.cnblogs.com/edmunds/p/13467020.html