您的位置:首页 > 其它

ZOJ - 3261 逆向并查集

2017-04-02 22:08 357 查看
             思路:很巧妙的解法。如果按照常规一边读入,一边合并并查集,删边实在没办法做。

          首先读入所有的操作,把所有不会被删除的边加入并查集,然后从最后一个操作开始逆向操作,当遇到删边操作,就直接把这条边加入并查集。可以用一个栈保存答案。

        注意:当有两个power相同的时候,选择编号更小的。输出之间有空行。

AC代码

#include <cstdio>
#include <cmath>
#include <cctype>
#include <algorithm>
#include <cstring>
#include <utility>
#include <string>
#include <iostream>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <stack>
using namespace std;
#pragma comment(linker, "/STACK:1024000000,1024000000")
#define eps 1e-10
#define inf 0x3f3f3f3f
#define PI pair<int, int>
typedef long long LL;
const int maxn = 1e4 + 5;
int p[maxn], a[maxn];
struct node{
int x, y;
}b[maxn<<1];

struct oper{
char s[20];
int x, y;
}q[maxn*5];

int find(int x) {
return p[x] == x ? x : p[x] = find(p[x]);
}

void unionset(int x, int y) {
int rx = find(x), ry = find(y);
if(a[rx] == a[ry]) { //当二者的值相同
if(rx < ry) p[ry] = rx;
else p[rx] = ry;
}
else if(a[rx] < a[ry]) {
p[rx] = ry;
}
else p[ry] = rx;
}

int main() {
int n, m, kase = 0;
while(scanf("%d", &n) == 1) {
if(kase++) printf("\n");
for(int i = 0; i <= n; ++i) p[i] = i;
for(int i = 0; i < n; ++i) scanf("%d", &a[i]);
scanf("%d", &m);
int x, y;
for(int i = 1; i <= m; ++i) {
scanf("%d%d", &b[i].x, &b[i].y);
if(b[i].x > b[i].y) swap(b[i].x, b[i].y);
}
int Q;
scanf("%d", &Q);
getchar();
map<PI, int>ha;
char s[30];
for(int i = 1; i <= Q; ++i) {
fgets(s, sizeof(s), stdin);
if(s[0] == 'd') {
sscanf(s, "%s%d%d", &q[i].s, &q[i].x, &q[i].y);
if(q[i].x > q[i].y) swap(q[i].x, q[i].y);
PI pi = make_pair(q[i].x, q[i].y);
ha[pi] = 1;
//printf("%s %d %d\n", q[i].s, q[i].x, q[i].y);
}
else {
sscanf(s, "%s%d", &q[i].s, &q[i].x);
//printf("%s %d\n", q[i].s, q[i].x);
}
}
//建立并查集
for(int i = 1; i <= m; ++i) {
if(!ha.count(make_pair(b[i].x, b[i].y))) {
unionset(b[i].x, b[i].y);
}
}
//逆向
stack<int>ans;
for(int i = Q; i > 0; --i) {
if(q[i].s[0] == 'q') {
int r = find(q[i].x);
if(a[r] <= a[q[i].x]) ans.push(-1);
else ans.push(r);
}
else unionset(q[i].x, q[i].y);
}
while(!ans.empty()) {
printf("%d\n", ans.top());
ans.pop();
}
}
return 0;
}

如有不当之处欢迎指出!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: