HDU 5458 Stability

Stability

Time Limit: 2000ms
Memory Limit: 102400KB
This problem will be judged on HDU. Original ID: 5458
64-bit integer IO format: %I64d      Java class name: Main
 

Given an undirected connected graph G with n nodes and m edges, with possibly repeated edges and/or loops. The stability of connectedness between node u and node v is defined by the number of edges in this graph which determines the connectedness between them (once we delete this edge, node u and v would be disconnected).

You need to maintain the graph G, support the deletions of edges (though we guarantee the graph would always be connected), and answer the query of stability for two given nodes.


Input
There are multiple test cases(no more than 3 cases), and the first line contains an integer t, meaning the totally number of test cases.

For each test case, the first line contains three integers n, m and q, where 1≤n≤3×104,1≤m≤105 and 1≤q≤105. The nodes in graph G are labelled from 1 to n.

Each of the following m lines contains two integers u and v describing an undirected edge between node u and node v.

Following q lines - each line describes an operation or a query in the formats:
⋅ 1 a b: delete one edge between a and b. We guarantee the existence of such edge.
⋅ 2 a b: query the stability between a and b.


Output
For each test case, you should print first the identifier of the test case.

Then for each query, print one line containing the stability between corresponding pair of nodes.


Sample Input
1
10 12 14
1 2
1 3
2 4
2 5
3 6
4 7
4 8
5 8
6 10
7 9
8 9
8 10
2 7 9
2 7 10
2 10 6
2 10 5
1 10 6
2 10 1
2 10 6
2 3 10
1 8 5
2 5 10
2 4 5
1 7 9
2 7 9
2 10 5


Sample Output
Case #1:
0
0
0
0
2
4
3
3
2
3
4


Source
2015 ACM/ICPC Asia Regional Shenyang Online

解题:树链剖分

逆向操作,把删边视为加边,除去删除的那些边,玩树链剖分,首先,你得有棵树,没树,什么都是扯淡。

我们把要删的那些边从图上统统删除,剩下的残图不一定就是树,所以用并查集在残图上找棵树,树的边权都设为1,然后把残图中不在树上的边都加到树上,这样形成环了,那么把环上的树边全部置0.

现在开始删边(实际是加边,因为逆序操作)和查询,是的,逆序的,每次加边,就把形成的环,环上的树边都置成0,查询就查询这条路径上的边权和即可

 

  1 #include <iostream>
  2 #include <stdio.h>
  3 #include <set>
  4 #include <algorithm>
  5 #include <cstring>
  6 using namespace std;
  7 typedef pair<int,int> PII;
  8 const int maxn = 200010;
  9 struct arc {
 10     int to,next;
 11     arc(int x = 0,int y = -1) {
 12         to = x;
 13         next = y;
 14     }
 15 } e[maxn<<1];
 16 struct node {
 17     int lt,rt,sum,lazy;
 18 } tree[maxn<<2];
 19 int head[maxn],tot;
 20 void add(int u,int v) {
 21     e[tot] = arc(v,head[u]);
 22     head[u] = tot++;
 23 }
 24 inline void pushup(int v) {
 25     tree[v].sum = tree[v<<1].sum + tree[v<<1|1].sum;
 26 }
 27 inline void pushdown(int v) {
 28     if(~tree[v].lazy) {
 29         tree[v<<1].sum = (tree[v<<1].rt - tree[v<<1].lt + 1)*tree[v].lazy;
 30         tree[v<<1].lazy = tree[v].lazy;
 31         tree[v<<1|1].sum = (tree[v<<1|1].rt - tree[v<<1|1].lt + 1)*tree[v].lazy;
 32         tree[v<<1|1].lazy = tree[v].lazy;
 33         tree[v].lazy = -1;
 34     }
 35 }
 36 void build(int lt,int rt,int v) {
 37     tree[v].lt = lt;
 38     tree[v].rt = rt;
 39     tree[v].lazy = -1;
 40     if(lt == rt) {
 41         tree[v].sum = 1;
 42         return;
 43     }
 44     int mid = (lt + rt)>>1;
 45     build(lt,mid,v<<1);
 46     build(mid + 1,rt,v<<1|1);
 47     pushup(v);
 48 }
 49 void update(int lt,int rt,int val,int v) {
 50     if(lt <= tree[v].lt && rt >= tree[v].rt) {
 51         tree[v].sum = (tree[v].rt - tree[v].lt + 1)*val;
 52         tree[v].lazy = val;
 53         return;
 54     }
 55     pushdown(v);
 56     if(lt <= tree[v<<1].rt) update(lt,rt,val,v<<1);
 57     if(rt >= tree[v<<1|1].lt) update(lt,rt,val,v<<1|1);
 58     pushup(v);
 59 }
 60 int query(int lt,int rt,int v) {
 61     if(lt == tree[v].lt && rt == tree[v].rt) return tree[v].sum;
 62     pushdown(v);
 63     int mid = (tree[v].lt + tree[v].rt)>>1;
 64     if(rt <= mid) return query(lt,rt,v<<1);
 65     if(lt > mid) return query(lt,rt,v<<1|1);
 66     return query(lt,mid,v<<1) + query(mid + 1,rt,v<<1|1);
 67 }
 68 int fa[maxn],dep[maxn],top[maxn],siz[maxn],son[maxn],loc[maxn],cnt;
 69 void FindHeavyEdge(int u,int father,int depth) {
 70     fa[u] = father;
 71     dep[u] = depth;
 72     siz[u] = 1;
 73     son[u] = -1;
 74     for(int i = head[u]; ~i; i = e[i].next) {
 75         if(e[i].to == father) continue;
 76         FindHeavyEdge(e[i].to,u,depth + 1);
 77         siz[u] += siz[e[i].to];
 78         if(son[u] == -1 || siz[son[u]] < siz[e[i].to])
 79             son[u] = e[i].to;
 80     }
 81 }
 82 void ConnectHeavyEdge(int u,int ancestor) {
 83     top[u] = ancestor;
 84     loc[u] = ++cnt;
 85     if(son[u] != -1) ConnectHeavyEdge(son[u],ancestor);
 86     for(int i = head[u]; ~i; i = e[i].next) {
 87         if(e[i].to == fa[u] || e[i].to == son[u]) continue;
 88         ConnectHeavyEdge(e[i].to,e[i].to);
 89     }
 90 }
 91 void UPDATE(int u,int v,int val = 0) {
 92     while(top[u] != top[v]) {
 93         if(dep[top[u]] < dep[top[v]]) swap(u,v);
 94         update(loc[top[u]],loc[u],val,1);
 95         u = fa[top[u]];
 96     }
 97     if(u == v) return;
 98     if(dep[u] > dep[v]) swap(u,v);
 99     update(loc[son[u]],loc[v],val,1);
100 }
101 int QUERY(int u,int v,int ret = 0) {
102     while(top[u] != top[v]) {
103         if(dep[top[u]] < dep[top[v]]) swap(u,v);
104         ret += query(loc[top[u]],loc[u],1);
105         u = fa[top[u]];
106     }
107     if(u == v) return ret;
108     if(dep[u] > dep[v]) swap(u,v);
109     return ret + query(loc[son[u]],loc[v],1);
110 }
111 int u,v,ans[maxn],uf[maxn],op[maxn],x[maxn],y[maxn];
112 bool used[maxn];
113 int Find(int x) {
114     if(x != uf[x]) uf[x] = Find(uf[x]);
115     return uf[x];
116 }
117 multiset<PII>S,V;
118 int main() {
119     int kase,n,m,q,cs = 1;
120     scanf("%d",&kase);
121     while(kase--) {
122         S.clear();
123         V.clear();
124         scanf("%d%d%d",&n,&m,&q);
125         for(int i = tot = cnt = 0; i < m; ++i) {
126             scanf("%d%d",&u,&v);
127             if(u > v) swap(u,v);
128             S.insert(PII(u,v));
129         }
130         for(int i = 0; i <= n; ++i) {
131             head[i] = -1;
132             used[i] = false;
133             uf[i] = i;
134         }
135         for(int i = 0; i < q; ++i) {
136             scanf("%d%d%d",op + i,x + i,y + i);
137             if(x[i] > y[i]) swap(x[i],y[i]);
138             if(op[i] == 1) S.erase(S.find(PII(x[i],y[i])));
139         }
140         for(auto &it:S) {
141             int a = Find(it.first),b = Find(it.second);
142             if(a != b) {
143                 V.insert(it);
144                 add(it.first,it.second);
145                 add(it.second,it.first);
146                 uf[a] = b;
147             }
148         }
149         FindHeavyEdge(1,0,0);
150         ConnectHeavyEdge(1,1);
151         build(1,cnt,1);
152         for(auto &it:S)
153             if(V.find(it) == V.end()) UPDATE(it.first,it.second);
154         for(int i = q-1; i >= 0; --i)
155             if(op[i] == 1) UPDATE(x[i],y[i]);
156             else if(op[i] == 2) ans[i] = QUERY(x[i],y[i]);
157         printf("Case #%d:\n",cs++);
158         for(int i = 0; i < q; ++i)
159             if(op[i] == 2) printf("%d\n",ans[i]);
160     }
161     return 0;
162 }
View Code

 

posted @ 2015-10-18 15:20  狂徒归来  阅读(284)  评论(0编辑  收藏  举报