思路: 带权并查集
分析:
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; }
时间: 2024-10-21 20:35:37