HDU 6200 边双联通分量 + 并查集 + dfs序 + BIT
2017-10-07 18:33
627 查看
简略题意:初始给出一张无向图,两种操作:
1. 添加一条(u,v)的无向边。
2. 问从u到v的路径上的割边有多少。
假若不考虑添加边的操作,问有多少割边,我们只需要边双联通缩个点成树,树上的每个边都是割边。从而转化成树上两点间距离。从根dfs一下转化成有根树的问题。
现在考虑添加边的过程,其实就是再缩点的过程,先不考虑如何缩点,假如缩了点之后,我们就需要动态更新两点间距离了。对此我们只需要用dfs序 + BIT维护每个点到根的距离即可。每次一个边(u−>v)如果失去了作用,那么以v为根的子树的值都需要−1。
考虑这个再缩点的过程,其实我们可以用并查集来维护,每个集合的根部点都代表了实际还存在的点。加入我们要把(u,v)相连,那么先找到lc=lca(u,v),我们只需要暴力的把u和v向lc靠近,删除连接他们的边对答案的影响即可。
如果觉得我说的不是很清楚,可以参考叉姐的说法QAQ->ICPCCAMP。
1. 添加一条(u,v)的无向边。
2. 问从u到v的路径上的割边有多少。
假若不考虑添加边的操作,问有多少割边,我们只需要边双联通缩个点成树,树上的每个边都是割边。从而转化成树上两点间距离。从根dfs一下转化成有根树的问题。
现在考虑添加边的过程,其实就是再缩点的过程,先不考虑如何缩点,假如缩了点之后,我们就需要动态更新两点间距离了。对此我们只需要用dfs序 + BIT维护每个点到根的距离即可。每次一个边(u−>v)如果失去了作用,那么以v为根的子树的值都需要−1。
考虑这个再缩点的过程,其实我们可以用并查集来维护,每个集合的根部点都代表了实际还存在的点。加入我们要把(u,v)相连,那么先找到lc=lca(u,v),我们只需要暴力的把u和v向lc靠近,删除连接他们的边对答案的影响即可。
如果觉得我说的不是很清楚,可以参考叉姐的说法QAQ->ICPCCAMP。
#define others #ifdef poj #include <iostream> #include <cstring> #include <cmath> #include <cstdio> #include <algorithm> #include <vector> #include <string> #endif // poj #ifdef others #include <bits/stdc++.h> #endif // others //#define file #define all(x) x.begin(), x.end() using namespace std; const double eps = 1e-8; int dcmp(double x) { if(fabs(x)<=eps) return 0; return (x>0)?1:-1;}; typedef long long LL; namespace fastIO{ #define BUF_SIZE 100000 #define OUT_SIZE 100000 #define ll long long //fread->read bool IOerror=0; inline char nc(){ static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE; if (p1==pend){ p1=buf; pend=buf+fread(buf,1,BUF_SIZE,stdin); if (pend==p1){IOerror=1;return -1;} //{printf("IO error!\n");system("pause");for (;;);exit(0);} } return *p1++; } inline bool blank(char ch){return ch==' '||ch=='\n'||ch=='\r'||ch=='\t';} inline int read(int &x){ bool sign=0; char ch=nc(); x=0; for (;blank(ch);ch=nc()); if (IOerror)return 0; if (ch=='-')sign=1,ch=nc(); for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0'; if (sign)x=-x; return 1; } inline int read(ll &x){ bool sign=0; char ch=nc(); x=0; for (;blank(ch);ch=nc()); if (IOerror)return 0; if (ch=='-')sign=1,ch=nc(); for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0'; if (sign)x=-x; return 1; } inline int read(double &x){ bool sign=0; char ch=nc(); x=0; for (;blank(ch);ch=nc()); if (IOerror)return 0; if (ch=='-')sign=1,ch=nc(); for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0'; if (ch=='.'){ double tmp=1; ch=nc(); for (;ch>='0'&&ch<='9';ch=nc())tmp/=10.0,x+=tmp*(ch-'0'); } if (sign)x=-x; return 1; } inline int read(char *s){ char ch=nc(); for (;blank(ch);ch=nc()); if (IOerror)return 0; for (;!blank(ch)&&!IOerror;ch=nc())*s++=ch; *s=0; return 1; } inline void read(char &c){ for (c=nc();blank(c);c=nc()); if (IOerror){c=-1;return;} } //fwrite->write struct Ostream_fwrite{ char *buf,*p1,*pend; Ostream_fwrite(){buf=new char[BUF_SIZE];p1=buf;pend=buf+BUF_SIZE;} void out(char ch){ if (p1==pend){ fwrite(buf,1,BUF_SIZE,stdout);p1=buf; } *p1++=ch; } void print(int x){ static char s[15],*s1;s1=s; if (!x)*s1++='0';if (x<0)out('-'),x=-x; while(x)*s1++=x%10+'0',x/=10; while(s1--!=s)out(*s1); } void println(int x){ static char s[15],*s1;s1=s; if (!x)*s1++='0';if (x<0)out('-'),x=-x; while(x)*s1++=x%10+'0',x/=10; while(s1--!=s)out(*s1); out('\n'); } void print(ll x){ static char s[25],*s1;s1=s; if (!x)*s1++='0';if (x<0)out('-'),x=-x; while(x)*s1++=x%10+'0',x/=10; while(s1--!=s)out(*s1); } void println(ll x){ static char s[25],*s1;s1=s; if (!x)*s1++='0';if (x<0)out('-'),x=-x; while(x)*s1++=x%10+'0',x/=10; while(s1--!=s)out(*s1); out('\n'); } void print(double x,int y){ static ll mul[]={1,10,100,1000,10000,100000,1000000,10000000,100000000, 1000000000,10000000000LL,100000000000LL,1000000000000LL,10000000000000LL, 100000000000000LL,1000000000000000LL,10000000000000000LL,100000000000000000LL}; if (x<-1e-12)out('-'),x=-x;x*=mul[y]; ll x1=(ll)floor(x); if (x-floor(x)>=0.5)++x1; ll x2=x1/mul[y],x3=x1-x2*mul[y]; print(x2); if (y>0){out('.'); for (size_t i=1;i<y&&x3*mul[i]<mul[y];out('0'),++i); print(x3);} } void println(double x,int y){print(x,y);out('\n');} void print(char *s){while (*s)out(*s++);} void println(char *s){while (*s)out(*s++);out('\n');} void flush(){if (p1!=buf){fwrite(buf,1,p1-buf,stdout);p1=buf;}} ~Ostream_fwrite(){flush();} }Ostream; inline void print(int x){Ostream.print(x);} inline void println(int x){Ostream.println(x);} inline void print(char x){Ostream.out(x);} inline void println(char x){Ostream.out(x);Ostream.out('\n');} inline void print(ll x){Ostream.print(x);} inline void println(ll x){Ostream.println(x);} inline void print(double x,int y){Ostream.print(x,y);} inline void println(double x,int y){Ostream.println(x,y);} inline void print(char *s){Ostream.print(s);} inline void println(char *s){Ostream.println(s);} inline void println(){Ostream.out('\n');} inline void flush(){Ostream.flush();} }; using namespace fastIO; namespace solver { const int maxn = 100011; int n, m; vector<int> G[maxn]; struct A { int u, v, next; } star[2*maxn]; stack<int> S; int eg, head[maxn], dfn[maxn], low[maxn], towhere[maxn]; int Dindex, id; bool instack[maxn]; void addedge(int u, int v) { ++eg, star[eg] = {u, v, head[u]}, head[u] = eg; swap(u, v); ++eg, star[eg] = {u, v, head[u]}, head[u] = eg; } void dfsBCC(int u, int fa) { dfn[u] = low[u] = ++Dindex; S.push(u); instack[u] = 1; int v; for(int i = head[u]; ~i; i = star[i].next) { int v = star[i].v; if(v == fa) continue; if(!dfn[v]) { dfsBCC(v, u); low[u] = min(low[v], low[u]); } else if(instack[v]) { low[u] = min(low[u], dfn[v]); } } if(low[u] == dfn[u]) { id++; for(;;) { int tmp = S.top(); S.pop(); towhere[tmp] = id; instack[tmp] = 0; if(tmp == u) break; } } return ; } void init() { eg = Dindex = id = 0; memset(head, -1, sizeof head); while(!S.empty()) S.pop(); for(int i = 0; i < maxn; i++) G[i].clear(); memset(dfn, 0, sizeof dfn); memset(instack, 0, sizeof instack); memset(towhere, 0, sizeof towhere); } void rebuild() { for(int i = 1; i <= eg; i+=2) { int u = star[i].u, v = star[i].v; u = towhere[u], v = towhere[v]; if(u == v) continue; G[u].push_back(v); G[v].push_back(u); } } int time; int C[maxn]; int lowbit(int x) {return x&-x;}; void add(int x, int v) { for(int i = x; i <= time; i+=lowbit(i)) C[i]+=v; }; int ask(int x) { int res = 0; for(int i = x; i; i -= lowbit(i)) res += C[i]; return res;}; int fa[maxn], L[maxn], R[maxn]; int find(int x) { return x == fa[x]? x : fa[x] = find(fa[x]); } int p[20][maxn]; int deep[maxn]; void dfs(int u, int fa) { p[0][u] = fa; L[u] = ++time; for(auto v : G[u]) if(v != fa) { deep[v] = deep[u] + 1; dfs(v, u); } R[u] = time; } int goup(int x, int len) { for(int i = 19; i >= 0; i--) if(x != -1 && (len & (1 << i))) x = p[i][x]; return x; } int lca(int u, int v) { if(deep[u] < deep[v]) swap(u, v); int d = deep[u] - deep[v]; u = goup(u, d); if(v == u) return u; for(int i = 19; i >= 0; i--) { if(p[i][u] == p[i][v]) continue; u = p[i][u], v = p[i][v]; } return p[0][u]; } int solve() { init(); read(n), read(m); for(int i = 1; i <= m; i++) { int u, v; read(u), read(v); addedge(u, v); } for(int i = 1; i <= n; i++) if(!dfn[i]) dfsBCC(i, -1); rebuild(); memset(C, 0, sizeof C); time = 0; deep[1] = 0; dfs(1, -1); for(int i = 1; i < 20; i++) { for(int j = 1; j <= id; j++) { if(p[i-1][j] == -1) p[i][j] = -1; else p[i][j] = p[i-1][p[i-1][j]]; } } for(int i = 1; i <= id; i++) fa[i] = i, add(L[i], 1), add(R[i]+1, -1); int q; read(q); for(int i = 1; i <= q; i++) { int pt, x, y; read(pt); read(x); read(y); x = towhere[x], y = towhere[y]; if(pt == 1) { x = find(x), y = find(y); if(x == y) continue; int lc = lca(x, y); lc = find(lc); while(lc != x) { add(L[x], -1), add(R[x]+1, 1); fa[x] = lc; x = find(p[0][x]); } while(lc != y) { add(L[y], -1), add(R[y]+1, 1); fa[y] = lc; y = find(p[0][y]); } } else { x = find(x), y = find(y); int lc = lca(x, y); lc = find(lc); println(ask(L[x]) + ask(L[y]) - 2*ask(L[lc])); } } return 0; } } int main() { int t; scanf("%d", &t); for(int i = 1; i <= t; i++) { print("Case #"),print(i),print(":\n"); solver::solve(); } return 0; }
相关文章推荐
- hdu 1198 dfs||并查集求连通分量个数,关键建图
- hdu 1198 dfs||并查集求连通分量个数,关键建图
- HDU - 1213 dfs求联通块or并查集
- HDU 4738 Caocao's Bridges(双联通分量+并查集)
- hdu1198 Farm Irrigation(DFS,并查集)
- hdu 5739(点双联通分量 )
- [双联通分量 并查集] CEOI 2017. One-Way Streets
- HDU 3038 How Many Answers Are Wrong 带权并查集 dfs过程中维护变量
- hdu 1181 (搜索BFS,深搜DFS,并查集)
- poj1979 Red and Black(dfs判断联通分量)
- 【 CodeForces 209C】 【欧拉回路推结论+并查集计算联通分量】 【给定n点m边无向图,可能有自环和重边。 问最少添加多少条边后,使得图存在从点1出发发又回到点1的欧拉回路】
- [省选前题目整理][POJ 2942]Knights of the Round Table(Tarjan求点双联通分量+DFS对环染色)
- HDU 3639 强联通分量
- hdu1269 迷宫城堡 tarjan求强联通分量
- [强联通分量_DFS] 0725
- hdu 1181 (搜索BFS,深搜DFS,并查集)
- HDU 4635 强联通分量
- hdu1272---------------------并查集 + 判联通
- HDU 1269 迷宫城堡 (强联通分量,Tarjan算法)
- hdu 3352 求边双联通分量模板题(容器)