zoj 3261 Connections in Galaxy War

点击打开链接zoj 3261

思路: 带权并查集
分析:
1 题目说的是有n个星球0~n-1,每个星球都有一个战斗值。n个星球之间有一些联系,并且n个星球之间会有互相伤害
2 根本没有思路的题,看了网上的思路才知道是逆向并查集。如果我们按照正常的并查集来做,以战斗值最大为根节点的话,当询问的时候很容易,但是碰到删除边的时候就很困难了,所以这里才用逆向的并查集思路
3 我们先把所有的输入保存,然后我们可以这么考虑,从后面往前面枚举q次条件,如果是destroy我们认为是加边,这样的话就很好维护并查集了
4 但是这边我们还要考虑初始的状态,由于涉及到删边而且不一定是删除所有的边,所以我们只要在m个关系里面扣除要删除的边,然后建立集合做为初始的状态

代码:

#include<map>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std; const int MAXN = 50010; struct Node{
int mark;
int x;
int y;
};
Node node[MAXN];
Node edge[MAXN]; int n , m , q;
int val[MAXN];
int father[MAXN];
int ans[MAXN];
map<int , int>mp; void init(){
mp.clear();
for(int i = 0 ; i < n ; i++)
father[i] = i;
} int find(int x){
if(father[x] != x)
father[x] = find(father[x]);
return father[x];
} void Union(int x , int y){
int fx = find(x);
int fy = find(y);
if(fx != fy){
if(val[fx] > val[fy])
father[fy] = fx;
else if(val[fx] < val[fy])
father[fx] = fy;
else{
if(fx < fy)
father[fy] = fx;
else
father[fx] = fy;
}
}
} void solve(){
for(int i = 0 ; i < m ; i++){
if(mp[edge[i].x*MAXN+edge[i].y])
continue;
Union(edge[i].x , edge[i].y);
}
int pos = 0;
for(int i = q-1 ; i >= 0 ; i--){
if(node[i].mark == 0){
int fx = find(node[i].x);
// 这边不能写成的node[i].x != fx;
// 因为有可能跟节点和它的值相同
if(val[node[i].x] >= val[fx])
ans[pos++] = -1;
else
ans[pos++] = fx;
}
else
Union(node[i].x , node[i].y);
}
for(int i = pos-1 ; i >= 0 ; i--)
printf("%d\n" , ans[i]);
} int main(){
int x , y;
char str[10];
bool first = true;
while(scanf("%d" , &n) != EOF){
if(first)
first = false;
else
puts("");
for(int i = 0 ; i < n ; i++)
scanf("%d" , &val[i]);
init();
scanf("%d" , &m);
for(int i = 0 ; i < m ; i++){
scanf("%d%d" , &edge[i].x , &edge[i].y);
if(edge[i].x > edge[i].y)
swap(edge[i].x , edge[i].y);
}
scanf("%d" , &q);
for(int i = 0 ; i < q ; i++){
scanf("%s" , str);
if(str[0] == 'q'){
scanf("%d" , &node[i].x);
node[i].mark = 0;
}
else{
scanf("%d%d" , &node[i].x , &node[i].y);
if(node[i].x > node[i].y)
swap(node[i].x , node[i].y);
node[i].mark = 1;
mp[node[i].x*MAXN+node[i].y] = 1;
}
}
solve();
}
return 0;
}
上一篇:android开发学习笔记系列(2)-android应用界面编程


下一篇:windows server 2012 AD 活动目录部署系列(五)备份和还原域控制器