HDU 5458 Stability (树链剖分+并查集+set)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5458

给你n个点,m条边,q个操作,操作1是删边,操作2是问u到v之间的割边有多少条。

这题要倒着做才容易,倒着加边。

因为这题最后保证所有的点一定连通,所以可以构建一棵树,树链剖分一下。要是u到v之间只有一条边,那便是一条割边。而加边的话,就是将u到v之间的边权都+1,边权等于1的话是桥,大于1的话就不是了。所以我们初始化树的时候,可以将边权初始化为1,加边操作将边权赋值为0。求u到v的割边个数的话,就是求u到v的和。

中间存边我用multiset( map 超时),然后用并查集判断是不是一棵完整的树从而看情况加边。

  1 //#pragma comment(linker, "/STACK:102400000, 102400000")
  2 #include <algorithm>
  3 #include <iostream>
  4 #include <cstdlib>
  5 #include <cstring>
  6 #include <cstdio>
  7 #include <vector>
  8 #include <cmath>
  9 #include <ctime>
 10 #include <list>
 11 #include <set>
 12 #include <map>
 13 using namespace std;
 14 typedef long long LL;
 15 typedef pair <int, int> P;
 16 const int N = 1e5 + 5;
 17 struct Edge {
 18     int next, to;
 19 }edge[N << 1];
 20 multiset <P> myset; //存 构建的树的边
 21 int head[N], tot;
 22 int pre[N], son[N], dep[N], size[N], cnt; //son:重儿子
 23 int top[N], id[N];
 24 int uu[N], vv[N], c[N]; //q个操作c uu vv
 25 int x[N], y[N]; //开始输入的m条边x y
 26 int ans[N]; //答案
 27 int par[N]; //并查集
 28 
 29 void init(int n) {
 30     for(int i = 1; i <= n; ++i) {
 31         par[i] = i;
 32         head[i] = -1;
 33     }
 34     tot = cnt = 0;
 35     myset.clear();
 36 }
 37 
 38 inline void add(int u, int v) {
 39     edge[tot].next = head[u];
 40     edge[tot].to = v;
 41     head[u] = tot++;
 42 }
 43 
 44 inline int search(int n) {
 45     if(n == par[n])
 46         return n;
 47     return par[n] = search(par[n]);
 48 }
 49 
 50 void dfs1(int u, int p, int d) {
 51     dep[u] = d, size[u] = 1, son[u] = u, pre[u] = p;
 52     for(int i = head[u]; ~i; i = edge[i].next) {
 53         int v = edge[i].to;
 54         if(v == p)
 55             continue;
 56         dfs1(v, u, d + 1);
 57         if(size[v] >= size[son[u]])
 58             son[u] = v;
 59         size[u] += size[v];
 60     }
 61 }
 62 
 63 void dfs2(int u, int p, int t) {
 64     top[u] = t, id[u] = ++cnt;
 65     if(son[u] != u)
 66         dfs2(son[u], u, t);
 67     for(int i = head[u]; ~i; i = edge[i].next) {
 68         int v = edge[i].to;
 69         if(v == p || v == son[u])
 70             continue;
 71         dfs2(v, u, v);
 72     }
 73 }
 74 
 75 struct SegTree {
 76     int l, r, val, lazy, mid;
 77 }T[N << 2];
 78 
 79 void build(int p, int l, int r) {
 80     T[p].mid = (l + r) >> 1;
 81     T[p].l = l, T[p].r = r, T[p].lazy = 1;
 82     if(l == r) {
 83         T[p].val = 1;
 84         return ;
 85     }
 86     build(p << 1, l, T[p].mid);
 87     build((p << 1)|1, T[p].mid + 1, r);
 88     T[p].val = T[p << 1].val + T[(p << 1)|1].val;
 89 }
 90 
 91 inline void pushdown(int p) {
 92     int ls = p << 1, rs = (p << 1)|1;
 93     T[ls].lazy = T[rs].lazy = T[ls].val = T[rs].val = 0;
 94     T[p].lazy = 1;
 95 }
 96 
 97 void update(int p, int l, int r) {
 98     if(T[p].val == 0)
 99         return ;
100     if(T[p].l == l && T[p].r == r) {
101         T[p].lazy = T[p].val = 0;
102         return ;
103     }
104     if(!T[p].lazy) {
105         pushdown(p);
106     }
107     if(r <= T[p].mid) {
108         update(p << 1, l, r);
109     }
110     else if(l > T[p].mid) {
111         update((p << 1)|1, l, r);
112     }
113     else {
114         update(p << 1, l, T[p].mid);
115         update((p << 1)|1, T[p].mid + 1, r);
116     }
117     T[p].val = T[p << 1].val + T[(p << 1)|1].val;
118 }
119 
120 int query(int p, int l, int r) {
121     if(T[p].val == 0)
122         return 0;
123     if(T[p].l == l && T[p].r == r) {
124         return T[p].val;
125     }
126     if(!T[p].lazy) {
127         pushdown(p);
128     }
129     if(r <= T[p].mid) {
130          return query(p << 1 , l , r);
131      }
132      else if(l > T[p].mid) {
133          return query((p << 1)|1 , l , r);
134      }
135      else {
136          return query(p << 1 , l , T[p].mid) + query((p << 1)|1 , T[p].mid + 1 , r);
137      }
138 }
139 
140 void change(int u, int v) {
141     int fu = top[u], fv = top[v];
142     while(fu != fv) {
143         if(dep[fu] >= dep[fv]) {
144             update(1, id[fu], id[u]);
145             u = pre[fu];
146             fu = top[u];
147         }
148         else {
149             update(1, id[fv], id[v]);
150             v = pre[fv];
151             fv = top[v];
152         }
153     }
154     if(u == v)
155         return ;
156     else if(dep[u] >= dep[v])
157         update(1, id[son[v]], id[u]);
158     else
159         update(1, id[son[u]], id[v]);
160 }
161 
162 int find(int u, int v) {
163     int fu = top[u], fv = top[v], res = 0;
164     while(fu != fv) {
165         if(dep[fu] >= dep[fv]) {
166             res += query(1, id[fu], id[u]);
167             u = pre[fu];
168             fu = top[u];
169         }
170         else {
171             res += query(1, id[fv], id[v]);
172             v = pre[fv];
173             fv = top[v];
174         }
175     }
176     if(u == v)
177         return res;
178     else if(dep[u] >= dep[v])
179         return res + query(1, id[son[v]], id[u]);
180     else
181         return res + query(1, id[son[u]], id[v]);
182 }
183 
184 int main()
185 {
186     int t, n, m, q, u, v;
187     scanf("%d", &t);
188     for(int ca = 1; ca <= t; ++ca) {
189         scanf("%d %d %d", &n, &m, &q);
190         init(n);
191         for(int i = 1; i <= m; ++i) {
192             scanf("%d %d", x + i, y + i);
193             if(x[i] > y[i])
194                 swap(x[i], y[i]);
195             myset.insert(make_pair(x[i], y[i])); //先存边
196         }
197         for(int i = 1; i <= q; ++i) {
198             scanf("%d %d %d", c + i, uu + i, vv + i);
199             if(uu[i] > vv[i])
200                 swap(uu[i], vv[i]);
201             if(c[i] == 1) {
202                 auto pos = myset.find(make_pair(uu[i], vv[i])); //去除要删的边
203                 myset.erase(pos);
204             }
205         }
206         int f = 0;
207         for(auto i = myset.begin(); i != myset.end(); ++i) {
208             u = search(i->first), v = search(i->second);
209             if(u == v) { //不成环
210                 ++f;
211                 x[f] = i->first, y[f] = i->second; //此时的x y存的是非树也非删的边
212                 continue;
213             }
214             par[u] = v;
215             add(i->first, i->second);
216             add(i->second, i->first);
217         }
218         dfs1(1, -1, 0);
219         dfs2(1, -1, 1);
220         printf("Case #%d:\n", ca);
221         build(1, 2, n);
222         for(int i = 1; i <= f; ++i) {
223             change(x[i], y[i]);
224         }
225         f = 0;
226         for(int i = q; i >= 1; --i) {
227             if(c[i] == 1) {
228                 change(uu[i], vv[i]);
229             }
230             else {
231                 ans[++f] = find(uu[i], vv[i]);
232             }
233         }
234         for(int i = f; i >= 1; --i) {
235             printf("%d\n", ans[i]);
236         }
237     }
238     return 0;
239 }
View Code

写的我比较头痛,调试了比较久...

posted @ 2016-08-16 00:30  Recoder  阅读(439)  评论(0编辑  收藏  举报