Stability
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,查询就查询这条路径上的边权和即可
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
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 }