好久没写过这么长的代码了,题解东哥讲了那么多,并查集优化还是很厉害的,赶快做做前几天碰到的相似的题。

 #include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std; const int N = 1e5 + , M = 2e5 + ;
int head[N], ver[M * ], Next[M * ];
int dfn[N], low[N], n, m, tot, num;
bool bridge[M * ]; void add(int x, int y)
{
ver[++tot] = y, Next[tot] = head[x], head[x] = tot;
}
void tarjan(int x, int in_edge)
{
dfn[x] = low[x] = ++num;
for(int i = head[x]; i; i = Next[i])
{
int y = ver[i];
if(!dfn[y])
{
tarjan(y, i); ///节点 和 入边
low[x] = min(low[x], low[y]); if(low[y] > dfn[x])
{
bridge[i] = bridge[i ^ ] = true;
}
}
else if(i != (in_edge ^ )) ///搜索树上的边
{
low[x] = min(low[x], dfn[y]);
}
}
}
int c[N], dcc;
void dfs(int x)
{
c[x] = dcc;
for(int i = head[x]; i; i = Next[i])
{
int y = ver[i];
if(c[y] || bridge[i]) continue;
dfs(y);
}
}
const int maxn = N;
///加边
int cnt, h[maxn];
struct edge
{
int to, pre, v;
} e[maxn << ];
void add(int from, int to, int v)
{
cnt++;
e[cnt].pre = h[from]; ///5-->3-->1-->0
e[cnt].to = to;
e[cnt].v = v;
h[from] = cnt;
}
///LCA
int dist[maxn];
int dep[maxn];
int anc[maxn][]; ///2分的父亲节点
void dfs(int u, int fa)
{
for(int i = h[u]; i; i = e[i].pre)
{
int v = e[i].to;
if(v == fa) continue;
dist[v] = dist[u] + e[i].v;
dep[v] = dep[u] + ;
anc[v][] = u;
dfs(v, u);
}
}
void LCA_init(int n)
{
for(int j = ; ( << j) < n; j++)
for(int i = ; i <= n; i++) if(anc[i][j-])
anc[i][j] = anc[anc[i][j-]][j-];
}
int LCA(int u, int v)
{
int log;
if(dep[u] < dep[v]) swap(u, v);
for(log = ; ( << log) < dep[u]; log++);
for(int i = log; i >= ; i--)
if(dep[u] - ( << i) >= dep[v]) u = anc[u][i];
if(u == v) return u;
for(int i = log; i >= ; i--)
if(anc[u][i] && anc[u][i] != anc[v][i])
u = anc[u][i], v = anc[v][i];
return anc[u][];
}
int fa[N];
int Find(int x)
{
if(x == fa[x]) return x;
return fa[x] = Find(fa[x]);
}
int main()
{
int kase = ;
while(scanf("%d %d", &n, &m) != EOF)
{
if(n == && m == ) break;
tot = , dcc = , cnt = ;
for(int i = ; i <= n; i++) head[i] = , dfn[i] = , low[i] = , c[i] = , h[i] = ;
for(int i = ; i <= m * + ; i++) ver[i] = , Next[i] = , bridge[i] = false;
for(int i = ; i <= m; i++)
{
int x, y; scanf("%d %d", &x, &y);
add(x, y), add(y, x);
}
///求桥
for(int i = ; i <= n; i++)
{
if(!dfn[i]) tarjan(i, );
}
///求边双连通分量
for(int i = ; i <= n; i++)
{
if(!c[i])
{
++dcc;
dfs(i);
}
}
///缩点
for(int i = ; i <= tot; i++)
{
int x = ver[i ^ ], y = ver[i];
if(c[x] == c[y]) continue;
add(c[x], c[y], );
}
dfs(, );
LCA_init(dcc);
///并查集初始化
for(int i = ; i <= dcc; i++) fa[i] = i;
int Q; scanf("%d", &Q);
int ans = dcc - ;
printf("Case %d:\n", ++kase);
while(Q--)
{
int x, y; scanf("%d %d", &x, &y);
x = c[x], y = c[y];
int p = LCA(x, y);
x = Find(x);
while(dep[x] > dep[p])
{
fa[x] = anc[x][];
ans--;
x = Find(x);
}
y = Find(y);
while(dep[y] > dep[p])
{
fa[y] = anc[y][];
ans--;
y = Find(y);
}
printf("%d\n", ans);
}
}
return ;
}

POJ 3694 (tarjan缩点+LCA+并查集)的更多相关文章

  1. Poj 3694 Network (连通图缩点+LCA+并查集)

    题目链接: Poj 3694 Network 题目描述: 给出一个无向连通图,加入一系列边指定的后,问还剩下多少个桥? 解题思路: 先求出图的双连通分支,然后缩点重新建图,加入一个指定的边后,求出这条 ...

  2. POJ 3694Network(Tarjan边双联通分量 + 缩点 + LCA并查集维护)

    [题意]: 有N个结点M条边的图,有Q次操作,每次操作在点x, y之间加一条边,加完E(x, y)后还有几个桥(割边),每次操作会累积,影响下一次操作. [思路]: 先用Tarjan求出一开始总的桥的 ...

  3. POJ3694 Network 边双缩点+LCA+并查集

    辣鸡错误:把dfs和ldfs搞混...QAQ 题意:给定一个无向图,然后查询q次,求每次查询就在图上增加一条边,求剩余割边的个数. 先把边双缩点,然后预处理出LCA的倍增数组: 然后加边时,从u往上跳 ...

  4. POJ3694 Network —— 边双联通分量 + 缩点 + LCA + 并查集

    题目链接:https://vjudge.net/problem/POJ-3694 A network administrator manages a large network. The networ ...

  5. Codevs 3287 货车运输 2013年NOIP全国联赛提高组(带权LCA+并查集+最大生成树)

    3287 货车运输 2013年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 传送门 题目描述 Description A 国有 n 座 ...

  6. Tarjan 模板,高级并查集

    第一个模板有误!!!! 请见谅!!! 要怪就怪HDU吧,竟然让我过了 第二个模板是正确的.请翻到下面看更新 HDU 1269 评论区居然有人说用并查集过了,其实回想一下 求无向图的连通分量,就是并查集 ...

  7. 【CodeForces】827 D. Best Edge Weight 最小生成树+倍增LCA+并查集

    [题目]D. Best Edge Weight [题意]给定n个点m条边的带边权无向连通图,对每条边求最大边权,满足其他边权不变的前提下图的任意最小生成树都经过它.n,m<=2*10^5,1&l ...

  8. POJ 2762 tarjan缩点+并查集+度数

    Going from u to v or from v to u? Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 15494 ...

  9. Network POJ - 3694(lca并查集+连通图求桥)

    就是求出原先图中的桥的数量,在每一次询问时加入一条新边,求加入当前边后图中剩余的桥的数量 求出原先图中的桥的数量,然后减去新加入边的两端点之间的桥的数量,就是剩余桥的数量.. 用并查集把属于同一集合的 ...

随机推荐

  1. No-12.函数进阶

    函数进阶 目标 函数参数和返回值的作用 函数的返回值 进阶 函数的参数 进阶 递归函数 01. 函数参数和返回值的作用 函数根据 有没有参数 以及 有没有返回值,可以 相互组合,一共有 4 种 组合形 ...

  2. Spring对注解(Annotation)处理【转】

    1.从Spring2.0以后的版本中,spring也引入了基于注解(Annotation)方式的配置,注解(Annotation)是JDK1.5中引入的一个新特性,用于简化Bean的配置,某些场合可以 ...

  3. 使用custom elements和Shadow DOM自定义标签

    具体的api我就不写 官网上面多  如果不知道这个的话也可以搜索一下 目前感觉这个还是相当好用的直接上码. <!DOCTYPE html> <html lang="en&q ...

  4. sha1、base64、ase加密

    <!DOCTYPE html><html><head><title>sha1.base64.ase加密</title><meta ch ...

  5. GSS4 - Can you answer these queries IV || luogu4145上帝造题的七分钟2 / 花神游历各国 (线段树)

    GSS4 - Can you answer these queries IV || luogu4145上帝造题的七分钟2 / 花神游历各国 GSS4 - Can you answer these qu ...

  6. [LUOGU] P1063 能量项链

    题目描述 在Mars星球上,每个Mars人都随身佩带着一串能量项链.在项链上有N颗能量珠.能量珠是一颗有头标记与尾标记的珠子,这些标记对应着某个正整数.并且,对于相邻的两颗珠子,前一颗珠子的尾标记一定 ...

  7. GIMP做成颜色蒙板

    效果图: 原始的美女图片上盖了一层的颜色,这个是想出来的效果,只是用来实践学到的技能,具体的场景还没有确定. 1/首先打开原始的美女图片: 2/然后在添加一张新的图片,作为新的图层添加进来: 这样的话 ...

  8. android-csv-variants

    android-csv-variants https://github.com/zawn/android-csv-variants/ 目的 用于在Android Gradle构建时通过CSV文件配置V ...

  9. cookie小结(转)

    原文地址:http://www.cnblogs.com/xianyulaodi/p/6476991.html#_label0 作者:咸鱼老弟   阅读目录 什么是cookie       官方定义:N ...

  10. log4j动态日志级别调整

    1. 针对root logger的设置 log4j.rootLogger=INFO, CONSOLELogger.getRootLogger().setLevel(org.apache.log4j.L ...