ZOJ 3261 Connections in Galaxy War (逆向+带权并查集)
题意:有N个星球,每个星球有自己的武力值。星球之间有M条无向边,连通的两个点可以相互呼叫支援,前提是对方的武力值要大于自己。当武力值最大的伙伴有多个时,选择编号最小的。有Q次操作,destroy为切断连接两点的边,query为查询某星球能不能向它人呼叫支援。
还是需要离线逆向并查集求解。思路和HDU 4496很相似,但是此处不一定是把所有边都删去,所以需要删边的情况建立出最终的状态。因为N可以到1e4,所以可以用map嵌套map的方式记录过程中被删去的边,最后再根据删除情况建立状态。
在合并时需要维护自己能够申请到的支援的武力最大值,以及其编号。
1 #include<stdio.h> 2 #include<cstring> 3 #include<algorithm> 4 #include<iostream> 5 #include<cmath> 6 #include<map> 7 using namespace std; 8 typedef long long LL; 9 const int maxn = 2e4+5; 10 const int INF= 0x3f3f3f3f; 11 struct Edge{ 12 int u,v; 13 }E[maxn]; 14 struct Query{ 15 int op,a,b; 16 LL ans; 17 }p[maxn*3]; 18 LL w[maxn]; 19 LL dist[maxn]; 20 int fa[maxn]; 21 int maxid[maxn]; 22 inline int Find(int x) {return fa[x]==x ?x: fa[x]=Find(fa[x]);} 23 //void init(int N){ for(int i=0;i<N;++i) fa[i]=i,dist[i]=w[i],maxid[i]=i;} 24 void Union(int a,int b){ 25 a = Find(a),b = Find(b); 26 if(a!=b){ 27 fa[a] = b; 28 if(dist[b]<dist[a] || dist[b]==dist[a] && maxid[b]>maxid[a]){ 29 dist[b]=dist[a]; 30 maxid[b]= maxid[a]; 31 } 32 } 33 } 34 35 map<int,map<int,int> > tag; 36 37 int main() 38 { 39 #ifndef ONLINE_JUDGE 40 freopen("in.txt","r",stdin); 41 freopen("out.txt","w",stdout); 42 #endif 43 int T,N,M,Q,u,v,tmp,K,cas=1; 44 char op[10]; 45 int mk = 0; 46 while(scanf("%d",&N)==1){ 47 if(mk) printf("\n"); 48 mk = 1; 49 for(int i=0;i<N;++i) { 50 scanf("%lld",&w[i]); 51 fa[i]=maxid[i]=i; 52 dist[i]=w[i]; 53 } 54 tag.clear(); 55 scanf("%d",&M); 56 for(int i=1;i<=M;++i){ 57 scanf("%d%d",&u,&v); 58 E[i].u =u , E[i].v=v; 59 } 60 scanf("%d",&Q); 61 for(int i=1;i<=Q;++i){ 62 scanf("%s%d",op,&p[i].a); 63 if(op[0]=='d') { 64 p[i].op=0; 65 scanf("%d",&p[i].b); 66 tag[p[i].a][p[i].b]=tag[p[i].b][p[i].a]=1; //被删边的标记 67 } 68 else p[i].op = 1; //0删边,1查询 69 } 70 //因为并不是把边全删完,建立最终状态 71 for(int i=1;i<=M;++i){ 72 if(tag[E[i].u][E[i].v]) continue; //这条边不在 73 else Union(E[i].u,E[i].v); 74 } 75 76 for(int i=Q;i>=1;--i){ 77 if(!p[i].op) Union(p[i].a,p[i].b); 78 else{ 79 u = Find(p[i].a); 80 if(dist[u]>w[p[i].a]) p[i].ans=maxid[u]; 81 else p[i].ans= -1; 82 } 83 } 84 for(int i=1;i<=Q;++i){ 85 if(p[i].op) printf("%lld\n",p[i].ans); 86 } 87 } 88 return 0; 89 }
为了更好的明天