题目

给定一张NNN个点MMM条边的无向连通图,然后执行QQQ次操作,每次向图中添加一条边,并且询问当前无向图中“桥”的数量。

题解

  • 先求出图中所有的边双,然后缩点
  • 令c[x],c[y]c[x],c[y]c[x],c[y]为x,yx,yx,y所属边双的编号
  • 询问时若x,yx,yx,y同属一个e-DCC则割边数不变,若不在同一个边双内,缩点后的图变成了一棵树,树上的每一条边都为原图的割边,在x,yx,yx,y间加边那么树上从xxx到yyy的路径上的所有边都不再是割边,答案只需减去这些边。
  • 对于统计x,yx,yx,y路径上的边我们可以找x,yx,yx,y的lcalcalca暴力往上跳,但这样的复杂度是不优秀的,我们可以并查集来维护,这样复杂度降为O(M+Q×N)O(M+Q\times N)O(M+Q×N)

code

#include <bits/stdc++.h> using namespace std; template <class T> inline void read(T &s) {s = 0; T w = 1, ch = getchar(); while (!isdigit(ch)) { if (ch == '-') w = -1; ch = getchar(); }while (isdigit(ch)) { s = (s << 1) + (s << 3) + (ch ^ 48); ch = getchar(); }s *= w;
}const int N = 1e5 + 100;
const int M = 4e5 + 100;
const int Z = 21; int n, m, tot, tim, q, dcc, totc, T;
int lin[N], dfn[N], low[N], c[N], linc[N], fa[N];
int f[N][Z], d[N];
bool bridge[M];
struct edge {int next, to;
} e[M], ec[M]; inline void clean() {tot = 1, tim = 0, dcc = 0, totc = 1; for (int i = 1; i <= n; ++i) c[i] = lin[i] = linc[i] = dfn[i] = low[i] = 0; memset(bridge, false, sizeof(bridge));
}inline void add(int from, int to) {e[++tot].to = to; e[tot].next = lin[from]; lin[from] = tot;
}void tarjan(int u, int in_edge) {dfn[u] = low[u] = ++tim; for (int i = lin[u]; i; i = e[i].next) {int v = e[i].to; if (!dfn[v]) {tarjan(v, i); low[u] = min(low[u], low[v]); if (low[v] > dfn[u]) bridge[i] = bridge[i ^ 1] = true; }else if (i != (in_edge ^ 1)) low[u] = min(low[u], dfn[v]); }
}void dfs(int u) {c[u] = dcc; for (int i = lin[u]; i; i = e[i].next) {int v = e[i].to; if (bridge[i] || c[v]) continue; dfs(v); }
}inline void addc(int from, int to) {ec[++totc].to = to; ec[totc].next = linc[from]; linc[from] = totc;
}void bfs() {memset(d, 0, sizeof(d)); memset(f, 0, sizeof(f)); queue<int> q; q.push(1); d[1] = 1; while (!q.empty()) {int u = q.front(); q.pop(); for (int i = linc[u]; i; i = ec[i].next) {int v = ec[i].to; if (d[v]) continue; d[v] = d[u] + 1; f[v][0] = u; for (int j = 1; j < 20; ++j) f[v][j] = f[f[v][j - 1]][j - 1]; q.push(v); }}
}int lca(int x, int y) {if (d[x] < d[y]) swap(x, y); for (int i = 19; i >= 0; --i) {if (d[f[x][i]] >= d[y]) x = f[x][i]; }if (x == y) return x; for (int i = 19; i >= 0; --i) {if (f[x][i] != f[y][i]) x = f[x][i], y = f[y][i]; }return f[x][0];
}inline int get(int x) {return fa[x] == x ? x : fa[x] = get(fa[x]);
}int main() {freopen("1.in", "r", stdin); while (true) {read(n), read(m); if (!n || !m) break; clean(); for (int i = 1; i <= m; ++i) {int x, y; read(x), read(y); add(x, y); add(y, x); }for (int i = 1; i <= n; ++i) {if (!dfn[i]) tarjan(i, 0); }for (int i = 1; i <= n; ++i) {if (!c[i]) {++dcc, dfs(i); }}for (int i = 2; i <= tot; ++i) {int x = e[i].to, y = e[i ^ 1].to; if (c[x] == c[y]) continue; addc(c[x], c[y]); }bfs(); for (int i = 1; i <= dcc; ++i) fa[i] = i; int ans = dcc - 1; read(q); printf("Case %d:\n", ++T); while (q--) {int x, y; read(x), read(y); x = c[x], y = c[y]; int p = lca(x, y); x = get(x); while (d[x] > d[p]) {fa[x] = f[x][0]; ans--; x = get(x); }y = get(y); while (d[y] > d[p]) {fa[y] = f[y][0]; ans--; y = get(y); }printf("%d\n", ans); }puts(""); }return 0;
}

POJ 3694 Network(tarjan+lca+并查集)相关推荐

  1. 【割边缩点】解题报告:POJ - 3694 - Network(Tarjan割边缩点 + LCA + 并查集优化)

    POJ - 3694 - Network 给定一张N个点M条边的无向连通图,然后执行Q次操作,每次向图中添加一条边,并且询问当前无向图中"桥"的数量.N≤105,M≤2∗105,Q ...

  2. POJ 3694 (tarjan缩点+LCA+并查集)

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

  3. POJ 3694 Network ★(边双连通分量+并查集缩点+LCA)

    [题意]一个无向图可以有重边,下面q个操作,每次在两个点间连接一条有向边,每次连接后整个无向图还剩下多少桥(每次回答是在上一次连边的基础之上) [分析]好题,做完后涨了很多姿势~ 普通做法当然就是每加 ...

  4. POJ - 3694 Network(边双缩点+LCA+并查集优化)

    题目链接:点击查看 题目大意:给出一个由n个点组成的无向图,现在有m次操作,每次操作都会向图中增加一条无向边,每次操作后询问当前图中有多少个桥 题目分析:题意很好理解,思路也很好想,就是代码量有点小多 ...

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

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

  6. 食物链 POJ - 1182(带权并查集模板)

    动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种. 有人用两种 ...

  7. 51nod1743-雪之国度【最小生成树,LCA,并查集】

    正题 题目链接:http://www.51nod.com/Challenge/Problem.html#problemId=1743 题目大意 nnn个点mmm条边的一张图,每次询问要求找出x,yx, ...

  8. poj 1456 Supermarket (贪心, 并查集)

    链接: http://poj.org/problem?id=1456 题目: Description A supermarket has a set Prod of products on sale. ...

  9. poj 2492A Bug's Life(并查集)

    /* 目大意:输入一个数t,表示测试组数.然后每组第一行两个数字n,m,n表示有n只昆虫,编号从1-n,m表示下面要输入m行交配情况,每行两个整数,表示这两个编号的昆虫为异性,要交配. 要求统计交配过 ...

最新文章

  1. wpf richtextbox 存储到数据库并显示
  2. 【模型解读】pooling去哪儿了?
  3. 2021年5月信息系统项目管理师案例分析真题+视频讲解(1)
  4. [JavaScript]JS由来
  5. javascript计算小数保留两位小数,多位小数的方法
  6. HDU 5890 Eighty seven(DP+bitset优化)
  7. java compare equla_Java中的equals,==,compareTo和compare的比较
  8. JPA + EclipseLink + SAP云平台 = 运行在云端的数据库应用 1
  9. mysql mac版_MAMP Pro—PHP/MySQL开发环境
  10. VMware Cloud Director 严重漏洞可使整个云基础设施遭接管
  11. 【Yarn】工作机制及任务提交流程
  12. matlab向量的模
  13. 蒋清野《虚拟化、云计算、开放源代码及其他》
  14. 用中信证券示范大作手回忆录
  15. 三维重建:基于RGB-D相机的三维重建总览(静态动态)
  16. python中文分句_python实现中文文本分句的例子
  17. 小白也能行--李洵同款--动态爱心代码《附可跳动版本代码》
  18. 程序员,你应该读读这些书(豆瓣高分8.0 )
  19. 游戏 AI 设计之 FSM 有限状态机
  20. [UWP] ExReaderPlus 英语阅读软件

热门文章

  1. Swoft View 视图
  2. arc lint java,JavaFX 类 Arc用法及代码示例
  3. 打了WIN7的正版验证补丁后,再激活!
  4. 使用java.io.File操作文件及文件夹
  5. 使用 PyQT5 来做一个简易版库存管理系统(三)
  6. buuoj--easy_tornado
  7. [大数据概念]-- 大数据的技术生态比喻
  8. 《就业乱世,如何正面应战!【所长】》笔记
  9. golang安装protobuf以及go-micro
  10. 同轴高清技术---AHD/HD-CVI/HD-SDI/HD-TVI