题目:给出一些点,每个点有权值,然后有一些边,相连。无向的。然后有一些操作
query a.表示从a出发的能到达的所有点权值最大的点的编号(相同取编号最小,而且权值要比自己大)
destory a,b 表示删除连接a,b的边
思路并查集,但是要逆向处理,所以先离线读入,从后向前处理,于是对于destroy操作,等价于连接两个点的操作,然后对于每个询问输出即可
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
#include<stack>
#include<string>
#include<map>
#include<set>
#define eps 1e-6
#define LL long long
using namespace std;
const int maxn = 10000 + 100;
const int INF = 0x3f3f3f3f;
int val[maxn];
int n, m, q;
set<pair<int, int> > edge;
stack<char> op;
stack<int> query;
stack<pair<int, int> > destroy;
stack<int> ans;
int fa[maxn];
int kase = 0;
int find(int x) {
return x == fa[x] ? x : fa[x] = find(fa[x]);
}
void init() {
edge.clear();
for(int i = 0; i < n; i++) fa[i] = i;
for(int i = 0; i < n; i++) cin >> val[i];
cin >> m;
while(m--) {
int u, v; cin >> u >> v;
edge.insert(make_pair(u, v));
}
cin >> q;
while(q--) {
char cmd[7]; cin >> cmd;
int u, v;
if(cmd[0] == 'q') {
op.push('q');
cin >> u;
query.push(u);
}
else {
op.push('d');
cin >> u >> v;
if(edge.count(make_pair(u, v))) edge.erase(make_pair(u, v));
if(edge.count(make_pair(v, u))) edge.erase(make_pair(v, u));
destroy.push(make_pair(u, v));
}
}
}
void solve() {
if(kase++) cout << endl;
for(set<pair<int, int> >::iterator it = edge.begin(); it != edge.end(); it++) {
int u = (*it).first, v = (*it).second;
if(val[find(u)] > val[find(v)]) {
fa[fa[v]] = fa[u];
}
else if(val[fa[u]] == val[find(v)]) {
if(fa[u] < fa[v]) fa[fa[v]] = fa[u];
else fa[fa[u]] = fa[v];
}
else {
fa[fa[u]] = fa[v];
}
}
char cmd;
while(!op.empty()) {
cmd = op.top(); op.pop();
if(cmd == 'q') {
int qu = query.top(); query.pop();
if(val[find(qu)] > val[qu]) ans.push(fa[qu]);
else ans.push(-1);
}
else {
pair<int, int> tmp = destroy.top(); destroy.pop();
int u = tmp.first, v = tmp.second;
if(val[find(u)] > val[find(v)]) {
fa[fa[v]] = fa[u];
}
else if(val[fa[u]] == val[find(v)]) {
if(fa[u] < fa[v]) fa[fa[v]] = fa[u];
else fa[fa[u]] = fa[v];
}
else {
fa[fa[u]] = fa[v];
}
}
}
while(!ans.empty()) {
cout << ans.top() << endl;
ans.pop();
}
}
int main() {
//freopen("input.txt", "r", stdin);
while(scanf("%d", &n) == 1) {
init();
solve();
}
}
zoj 3261 Connections in Galaxy War(并查集+离线逆向操作)
原文地址:http://blog.csdn.net/u014664226/article/details/46649567