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

  1 #include <iostream>
  2 #include <algorithm>
  3 #include <cstdio>
  4 using namespace std;
  5
  6 const int N = 1e5 + 50, M = 2e5 + 50;
  7 int head[N], ver[M * 2], Next[M * 2];
  8 int dfn[N], low[N], n, m, tot, num;
  9 bool bridge[M * 2];
 10
 11 void add(int x, int y)
 12 {
 13     ver[++tot] = y, Next[tot] = head[x], head[x] = tot;
 14 }
 15 void tarjan(int x, int in_edge)
 16 {
 17     dfn[x] = low[x] = ++num;
 18     for(int i = head[x]; i; i = Next[i])
 19     {
 20         int y = ver[i];
 21         if(!dfn[y])
 22         {
 23             tarjan(y, i); ///节点 和 入边
 24             low[x] = min(low[x], low[y]);
 25
 26             if(low[y] > dfn[x])
 27             {
 28                 bridge[i] = bridge[i ^ 1] = true;
 29             }
 30         }
 31         else if(i != (in_edge ^ 1)) ///搜索树上的边
 32         {
 33             low[x] = min(low[x], dfn[y]);
 34         }
 35     }
 36 }
 37 int c[N], dcc;
 38 void dfs(int x)
 39 {
 40     c[x] = dcc;
 41     for(int i = head[x]; i; i = Next[i])
 42     {
 43         int y = ver[i];
 44         if(c[y] || bridge[i]) continue;
 45         dfs(y);
 46     }
 47 }
 48 const int maxn = N;
 49 ///加边
 50 int cnt, h[maxn];
 51 struct edge
 52 {
 53     int to, pre, v;
 54 } e[maxn << 1];
 55 void add(int from, int to, int v)
 56 {
 57     cnt++;
 58     e[cnt].pre = h[from]; ///5-->3-->1-->0
 59     e[cnt].to = to;
 60     e[cnt].v = v;
 61     h[from] = cnt;
 62 }
 63 ///LCA
 64 int dist[maxn];
 65 int dep[maxn];
 66 int anc[maxn][33]; ///2分的父亲节点
 67 void dfs(int u, int fa)
 68 {
 69     for(int i = h[u]; i; i = e[i].pre)
 70     {
 71         int v = e[i].to;
 72         if(v == fa) continue;
 73         dist[v] = dist[u] + e[i].v;
 74         dep[v] = dep[u] + 1;
 75         anc[v][0] = u;
 76         dfs(v, u);
 77     }
 78 }
 79 void LCA_init(int n)
 80 {
 81     for(int j = 1; (1 << j) < n; j++)
 82         for(int i = 1; i <= n; i++) if(anc[i][j-1])
 83         anc[i][j] = anc[anc[i][j-1]][j-1];
 84 }
 85 int LCA(int u, int v)
 86 {
 87     int log;
 88     if(dep[u] < dep[v]) swap(u, v);
 89     for(log = 0; (1 << log) < dep[u]; log++);
 90     for(int i = log; i >= 0; i--)
 91         if(dep[u] - (1 << i) >= dep[v]) u = anc[u][i];
 92     if(u == v) return u;
 93     for(int i = log; i >= 0; i--)
 94         if(anc[u][i] && anc[u][i] != anc[v][i])
 95             u = anc[u][i], v = anc[v][i];
 96     return anc[u][0];
 97 }
 98 int fa[N];
 99 int Find(int x)
100 {
101     if(x == fa[x]) return x;
102     return fa[x] = Find(fa[x]);
103 }
104 int main()
105 {
106     int kase = 0;
107     while(scanf("%d %d", &n, &m) != EOF)
108     {
109         if(n == 0 && m == 0) break;
110         tot = 1, dcc = 0, cnt = 0;
111         for(int i = 1; i <= n; i++) head[i] = 0, dfn[i] = 0, low[i] = 0, c[i] = 0, h[i] = 0;
112         for(int i = 1; i <= m * 2 + 1; i++) ver[i] = 0, Next[i] = 0, bridge[i] = false;
113         for(int i = 1; i <= m; i++)
114         {
115             int x, y; scanf("%d %d", &x, &y);
116             add(x, y), add(y, x);
117         }
118         ///求桥
119         for(int i = 1; i <= n; i++)
120         {
121             if(!dfn[i]) tarjan(i, 0);
122         }
123         ///求边双连通分量
124         for(int i = 1; i <= n; i++)
125         {
126             if(!c[i])
127             {
128                 ++dcc;
129                 dfs(i);
130             }
131         }
132         ///缩点
133         for(int i = 2; i <= tot; i++)
134         {
135             int x = ver[i ^ 1], y = ver[i];
136             if(c[x] == c[y]) continue;
137             add(c[x], c[y], 1);
138         }
139         dfs(1, 0);
140         LCA_init(dcc);
141         ///并查集初始化
142         for(int i = 1; i <= dcc; i++) fa[i] = i;
143         int Q; scanf("%d", &Q);
144         int ans = dcc - 1;
145         printf("Case %d:\n", ++kase);
146         while(Q--)
147         {
148             int x, y; scanf("%d %d", &x, &y);
149             x = c[x], y = c[y];
150             int p = LCA(x, y);
151             x = Find(x);
152             while(dep[x] > dep[p])
153             {
154                 fa[x] = anc[x][0];
155                 ans--;
156                 x = Find(x);
157             }
158             y = Find(y);
159             while(dep[y] > dep[p])
160             {
161                 fa[y] = anc[y][0];
162                 ans--;
163                 y = Find(y);
164             }
165             printf("%d\n", ans);
166         }
167     }
168     return 0;
169 }

转载于:https://www.cnblogs.com/wangwangyu/p/9682999.html

POJ 3694 (tarjan缩点+LCA+并查集)相关推荐

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

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

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

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

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

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

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

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

  5. POJ 1703 Find them, Catch them(并查集高级应用)

    POJ 1703 Find them, Catch them(并查集高级应用) 手动博客搬家:本文发表于20170805 21:25:49, 原地址https://blog.csdn.net/sunc ...

  6. POJ 1417 True Liars(路径压缩并查集+DP背包问题)

    POJ 1417 True Liars(路径压缩并查集+DP背包问题) http://poj.org/problem?id=1417 题意: 给出p1+p2个人,其中p1个是好人,p2个是坏人.然后有 ...

  7. POJ 3694 Network(tarjan+lca+并查集)

    题目 给定一张NNN个点MMM条边的无向连通图,然后执行QQQ次操作,每次向图中添加一条边,并且询问当前无向图中"桥"的数量. 题解 先求出图中所有的边双,然后缩点 令c[x],c ...

  8. POJ - 2513 Colored Sticks(字典树+并查集+欧拉回路)

    题目链接:点击查看 题目大意:给出n个木棍,问若两两相连,最终能否构成一根长直木棍,相连的规则是两个木棍的相接端点的颜色需要保持相同 题目分析:关于这个题目,我们可以将每个木棍视为一条边,每个木棍的两 ...

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

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

最新文章

  1. ICCV2021旷视研究院入选9篇paper介绍(检测+点云+图像配准等)
  2. ANSYS——后处理中单元表(ELEMENT table)的作用、创建、使用
  3. 动态后台获取_后台管理系统的权限以及vue处理权限的思路
  4. Java ArrayList set()方法与示例
  5. 2018 A Sparse Topic Model for Extracting Aspect-Specific Summaries from Online Reviews 稀疏主题模型学习笔记
  6. substance design graph 不显示_每天1分钟背单词 词根 graph
  7. 封闭期5年的基金属于什么基金?
  8. SELECT INTO 和 replace into SELECT
  9. vc mysql ado blob_在VC下采用ADO实现BLOB(Binary)数据的存储,读取,修改,删除。...
  10. 组合数学1--组合数学简介
  11. 算法设计技巧与分析 答案整理
  12. 手机连上蓝牙耳机没有声音
  13. navigator 导航标签
  14. 时空恋旅人 豆瓣影评
  15. 怎样判断计算机硬盘损坏,检测硬盘是否损坏的方法来了,这里有四种判断方法!...
  16. Thinkphp6 搭建一套商城(拼团、秒杀、优惠券)
  17. Halide:简化图像编程
  18. 1.1 OpenFlow 概述
  19. 隆重推荐:大明王朝1566
  20. 如何成为一个高效、快乐、健康的程序员

热门文章

  1. thrift数据类型
  2. Android笔记一.深入理解Intent和IntentFilters(一)
  3. Eclipse工作空间还原到最初状态
  4. IT人士还是要善待自己
  5. File类的使用(java)
  6. 缓存框架(Java缓存)与框架缓存(介绍mybatis缓存)
  7. [python]练习之递归和循环实现斐波拉契数列
  8. 《深入实践Spring Boot》一第一部分 Part 1基础应用开发
  9. 使用AdMob实现广告统一
  10. 说说Thread.Sleep(0)的那些奇怪的事