题目:给出一些点,每个点有权值,然后有一些边,相连。无向的。然后有一些操作
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(); } }
时间: 2024-10-11 11:06:01