题目链接:

  Hdu 5458 Stability

题目描述:

  给出一个还有环和重边的图G,对图G有两种操作:

  1 u v, 删除u与v之间的一天边 (保证这个边一定存在)

  2 u v, 查询u到v的路径上有几条桥。

解题思路:

  这个题目有很多次操作,包含查询和删边两类,首先想到的是连通分量加缩点。如果按照顺序来,删边时候求桥就是问题了。所以可以离线处理,然后一边记录答案一边加边缩点。

  对于一个图,把连通分量缩成一个点后,这个图就成为了一棵树, 然后深度差就等于桥的数目。查询的时候对于(u, v)桥的数目等于(设定deep[x]为x的深度,LCA(x, y)为(x, y)的父节点) deep[u] + deep[v] - 2 * deep[LCA(u, v)];

  现在问题就成了怎么才能更快的缩点和维护点的深度。

  缩点问题:在树上加上一条边就会形成一个环,然后这个环(强连通分量)上点就会被缩成一个点,然后用并查集来维护强联通分量,每次只需要合并父节点(每个点只能被缩一次,复杂度被平摊还是很可观的)。

  维护节点深度:每次儿子节点合并到父亲节点的时候,儿子节点的子孙节点的深度都要减一。在这里我们可以用dfs序 + 树状数组来维护节点的深度。利用树状数组的区间更改点查询优化维护深度的操作。

  还有最后一个问题就是计算(u, v)节点之间桥数目的时候,需要用到LCA,可以利用树上倍增LCA来优化时间复杂度。

这个题目还是很值得本扎扎练手的,考察了很多东西,真是把压箱底的东西都翻出来晒了晒,仰慕当场ac的聚聚们。

 #include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = ;
const int N = ;
const int M = ; struct node
{
int to, del;
node(int x):to(x),del() {}
bool operator < (const node & a) const
{
if (to != a.to) return to < a.to;
return del > a.del;
}
};
vector <node> vec[maxn]; struct Query
{
int op, u, v;
void read ()
{
scanf ("%d %d %d", &op, &u, &v);
if (op == )
{
lower_bound (vec[u].begin(), vec[u].end(), node(v)) -> del = true;
lower_bound (vec[v].begin(), vec[v].end(), node(u)) -> del = true;
}
}
} query[N]; int n, m, q; void init ()
{
for (int i=; i<=n; i++)
vec[i].clear();
} struct bit_tree
{
int tree[maxn]; void init()
{
memset (tree, , sizeof(tree));
} int lowbit (int x)
{
return x & (-x);
} void change (int x, int num)
{
while (x <= n)
{
tree[x] += num;
x += lowbit (x);
}
} void update (int x, int y, int num)
{
change (x, num);
change (y+, -num);
} int query (int x)
{
int res = ;
while (x)
{
res += tree[x];
x -= lowbit (x);
}
return res;
} }Bit_tree; int begin_id[maxn], end_id[maxn], deep[maxn], ntime;
int fa[maxn][M];
void dfs (int u, int father, int dep)
{
if (father > )
vec[u].erase (lower_bound(vec[u].begin(), vec[u].end(), node(father))); fa[u][] = father;
begin_id[u] = ++ntime;
deep[u] = dep; for (int i=; i<vec[u].size(); i++)
{
node p = vec[u][i];
if (p.del || begin_id[p.to]) continue;
vec[u][i].del = true;
dfs (p.to, u, dep+);
} end_id[u] = ntime;
Bit_tree.update (begin_id[u], end_id[u], );
} struct Lca
{
void init ()
{
for (int i=; i<M; i++)
for (int j=; j<=n; j++)
fa[j][i] = fa[fa[j][i-]][i-];
} int lca (int u, int v)
{
if (deep[u] < deep[v]) swap (u, v);
int num = deep[u] - deep[v];
for (int i=; i<M; i++)
if ((<<i) & num) u = fa[u][i];
if (u == v) return u;
for (int i=M-; i>=; i--)
if (fa[u][i] != fa[v][i])
{
u = fa[u][i];
v = fa[v][i];
}
return fa[u][];
} }LCA; int father[maxn];
struct UNion
{
void init()
{
for (int i=; i<=n; i++)
father[i] = i;
} int find (int x)
{
if (x != father[x]) father[x] = find (father[x]);
return father[x];
} void merge_fa (int x, int y)
{
x = find (x);
while (x != y)
{
int t = find(fa[x][]);
father[x] = t;
Bit_tree.update(begin_id[x], end_id[x], -);
x = t;
}
} void merge (int x, int y)
{
int l = find (LCA.lca (x, y));
merge_fa (x, l);
merge_fa (y, l);
} }Union; int ans[N], res;
void solve ()
{
Bit_tree.init ();
ntime = res = ;
memset (begin_id, , sizeof(begin_id));
dfs (, , );
LCA.init ();
Union.init(); for (int i=; i<=n; i++)
{
for (int j=; j<vec[i].size(); j++)
{
node p = vec[i][j];
if (p.del) continue;
Union.merge (p.to, i);
}
} for (int i=q; i>; i--)
{
Query p = query[i];
int u = begin_id[p.u];
int v = begin_id[p.v];
int x = begin_id[LCA.lca(p.u, p.v)];
if (p.op == )
Union.merge(p.u, p.v);
else
ans[++ res] = Bit_tree.query(u) + Bit_tree.query(v) - *Bit_tree.query(x);
} while(res)
printf ("%d\n", ans[res --]);
} int main ()
{
int t, u, v;
scanf ("%d", &t); for (int i=; i<=t; i++)
{
scanf("%d %d %d", &n, &m, &q);
init (); for (int j=; j<m; j++)
{
scanf ("%d %d", &u, &v);
vec[u].push_back (node(v));
vec[v].push_back (node(u));
} for (int j=; j<=n; j++)
sort (vec[j].begin(), vec[j].end()); for (int j=; j<=q; j++)
query[j].read(); printf ("Case #%d:\n", i);
solve (); }
return ;
}

  

Hdu 5458 Stability (LCA + 并查集 + 树状数组 + 缩点)的更多相关文章

  1. hdu 6200 mustedge mustedge(并查集+树状数组 或者 LCT 缩点)

    hdu 6200 mustedge mustedge(并查集+树状数组 或者 LCT 缩点) 题意: 给一张无向连通图,有两种操作 1 u v 加一条边(u,v) 2 u v 计算u到v路径上桥的个数 ...

  2. HDU 5458 Stability(双连通分量+LCA+并查集+树状数组)(2015 ACM/ICPC Asia Regional Shenyang Online)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5458 Problem Description Given an undirected connecte ...

  3. BZOJ-3211花神游历各国 并查集+树状数组

    一开始想写线段树区间开方,简单暴力下,但觉得变成复杂度稍高,懒惰了,编了个复杂度简单的 3211: 花神游历各国 Time Limit: 5 Sec Memory Limit: 128 MB Subm ...

  4. BZOJ3211 花神游历各国 并查集 树状数组

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ3211 题意概括 有n个数形成一个序列. m次操作. 有两种,分别是: 1. 区间开根(取整) 2. ...

  5. 【bzoj4869】[Shoi2017]相逢是问候 扩展欧拉定理+并查集+树状数组

    题目描述 Informatik verbindet dich und mich. 信息将你我连结. B君希望以维护一个长度为n的数组,这个数组的下标为从1到n的正整数.一共有m个操作,可以分为两种:0 ...

  6. HDU 4750 Count The Pairs ★(图+并查集+树状数组)

    题意 给定一个无向图(N<=10000, E<=500000),定义f[s,t]表示从s到t经过的每条路径中最长的边的最小值.Q个询问,每个询问一个t,问有多少对(s, t)使得f[s, ...

  7. la4730(并查集+树状数组)

    https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=30& ...

  8. 【BZOJ3211】花神游历各国 并查集+树状数组

    [BZOJ3211]花神游历各国 Description Input Output 每次x=1时,每行一个整数,表示这次旅行的开心度 Sample Input 41 100 5 551 1 22 1 ...

  9. 【BZOJ4382】[POI2015]Podział naszyjnika 堆+并查集+树状数组

    [BZOJ4382][POI2015]Podział naszyjnika Description 长度为n的一串项链,每颗珠子是k种颜色之一. 第i颗与第i-1,i+1颗珠子相邻,第n颗与第1颗也相 ...

随机推荐

  1. hibernate 的分页查询

    hibernate的分页查询有个好处,就是不用管数据库方言.比如db2的分页查询很麻烦,但是用hibernate的方式,就完全不用管这些了 /* 使用HQL分页查询Customer信息 */ publ ...

  2. 备忘录模式-Memento

    备忘录模式:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态.这样以后就可以将该对象恢复到原先保存的状态. 备忘录模式结构图: 何时使用备忘录模式: Memento模式比适合 ...

  3. HttpSession and Hibernate session

    一.javax.servlet.http.HttpSession是一个抽象接口   它的产生:J2EE的Web程序在运行的时候,会给每一个新的访问者建立一个HttpSession,这个Session是 ...

  4. Spring Base

    1.在java开发领域,Spring相对于EJB来说是一种轻量级的,非侵入性的Java开发框架,曾经有两本很畅销的书<Expert one-on-one J2EE Design and Deve ...

  5. CH 5105 Cookies(贪心+DP)

    \(CH 5105 Cookies\) \(solution:\) 真是好题一道!这道题我想了很久很久,就得这一题可以直接完全贪心,可惜最后还是失败了,但是对贪心的深入思考也换来了一个最优解方案.然后 ...

  6. Latex 5: LaTeX资料下载

    转: LaTeX资料下载 最全latex资料下载   LaTeX命令速查手册1  

  7. CLI和CGI的区别

    CGI :“公共网关接口”(Common Gateway Interface),HTTP服务器与你的或其它机器上的程序进行“交谈”的一种工具,其程序须运行在网络服务器上.以CGI方式运行时,web s ...

  8. ie67 display:inline-block 失效解决方法

    先将其转化为块状,在转化为inline,*号为css hcak,代表针对IE67 display: inline-block; *display: block; *display: inline;

  9. Java DES加密解密

    import javax.crypto.Cipher; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.DESKeySpe ...

  10. Objective-C 中Socket常用转换机制(NSData,NSString,int,Uint8,Uint16,Uint32,byte[])

    最近项目中要用到socket通讯,由于涉及到组包问题,所以需要数据类型之间的来回转换,现在分享出来 如果想要请教Socket的问题请留言,我会随时回答的 1. int类型转16进制hexstring ...