[ZOJ3261]Connections in Galaxy War(离线,带权并查集)

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3261

题意:n个星球,起始有m个联通的条件。接下来会有q次查询,2种,一种是摧毁x和y的联通,另外一种是查询与x联通的星球里p大、id最小的星球。

离线,首先存下初始状态,接着存query,每一次query要修改一下初始状态的联通情况,最后倒着处理query。即每次摧毁变成unite。并查集合并的时候按照p大id小的顺序合并。

查询的时候直接找根就行了。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 typedef struct Query {
 5     char cmd;
 6     int x, y;
 7     Query() {}
 8     Query(char c, int x, int y) : cmd(c), x(x), y(y) {}
 9 }Query;
10 const int maxn = 10100;
11 set<int> G[maxn];
12 vector<Query> ask;
13 int n, m, q, p[maxn], pre[maxn];
14 vector<int> ret;
15 char cmd[5];
16 inline int find(int x) { return x == pre[x] ? x : pre[x] = find(pre[x]); }
17 inline void unite(int x, int y) {
18     x = find(x); y = find(y);
19     if(x == y) return;
20     if(p[x] > p[y]) pre[y] = x;
21     else if(p[x] < p[y]) pre[x] = y;
22     else pre[max(x, y)] = min(x, y);
23 }
24 
25 signed main() {
26     // freopen("in", "r", stdin);
27     int u, v;
28     int _ = 0;
29     while(~scanf("%d",&n)) {
30         if(_) puts("");
31         _++;
32         ask.clear(); ret.clear();
33         for(int i = 0; i < n; i++) pre[i] = i, G[i].clear();
34         for(int i = 0; i < n; i++) scanf("%d", &p[i]);
35         scanf("%d",&m);
36         for(int i = 0; i < m; i++) {
37             scanf("%d%d",&u,&v);
38             G[u].insert(v);
39             G[v].insert(u);
40         }
41         scanf("%d",&q);
42         while(q--) {
43             scanf("%s", cmd);
44             if(cmd[0] == 'q') {
45                 scanf("%d",&u);
46                 ask.push_back(Query('q',u,-1));
47             }
48             else {
49                 scanf("%d%d",&u,&v);
50                 ask.push_back(Query('d',u,v));
51                 if(G[u].find(v) != G[u].end()) G[u].erase(v);
52                 if(G[v].find(u) != G[v].end()) G[v].erase(u);
53             }
54         }
55         for(int u = 0; u < n; u++) {
56             for(set<int>::iterator v = G[u].begin(); v !=G[u].end(); v++) {
57                 unite(u, *v);
58             }
59         }
60         for(int i = ask.size()-1; i >= 0; i--) {
61             if(ask[i].cmd == 'q') {
62                 if(p[find(ask[i].x)] <= p[ask[i].x]) ret.push_back(-1);
63                 else ret.push_back(find(ask[i].x));
64             }
65             else unite(ask[i].x, ask[i].y);
66         }
67         for(int i = ret.size()-1; i >= 0; i--) printf("%d\n", ret[i]);
68     }
69     return 0;
70 }

 

posted @ 2017-06-16 11:05  Kirai  阅读(144)  评论(0编辑  收藏  举报