Network POJ-3694

Network POJ-3694

文章目录

    • Description
    • 题意:
    • 样例分析:
    • 题解:
    • 代码:

Description

A network administrator manages a large network. The network consists
of N computers and M links between pairs of computers. Any pair of
computers are connected directly or indirectly by successive links, so
data can be transformed between any two computers. The administrator
finds that some links are vital to the network, because failure of any
one of them can cause that data can’t be transformed between some
computers. He call such a link a bridge. He is planning to add some
new links one by one to eliminate all bridges.

You are to help the administrator by reporting the number of bridges
in the network after each new link is added.

Input

The input consists of multiple test cases. Each test case starts with
a line containing two integers N(1 ≤ N ≤ 100,000) and M(N - 1 ≤ M ≤
200,000). Each of the following M lines contains two integers A and B
( 1≤ A ≠ B ≤ N), which indicates a link between computer A and B.
Computers are numbered from 1 to N. It is guaranteed that any two
computers are connected in the initial network. The next line contains
a single integer Q ( 1 ≤ Q ≤ 1,000), which is the number of new links
the administrator plans to add to the network one by one. The i-th
line of the following Q lines contains two integer A and B (1 ≤ A ≠ B
≤ N), which is the i-th added new link connecting computer A and B.

The last test case is followed by a line containing two zeros.

Output

For each test case, print a line containing the test case number(
beginning with 1) and Q lines, the i-th of which contains a integer
indicating the number of bridges in the network after the first i new
links are added. Print a blank line after the output for each test
case.

Sample Input

3 2
1 2
2 3
2
1 2
1 3
4 4
1 2
2 1
2 3
1 4
2
1 2
3 4
0 0

Sample Output

Case 1:
1
0Case 2:
2
0

题意:

n个点,m个边
点与点之间通过边连接,如果切断某个边使得有点与其他点连接断开(连通分支增加),则称这种边为桥梁(离散上叫割边)。
接下来有Q个操作,每操作一次,输出当前存在的桥梁数量

样例分析:

我们看这个
4 4
1 2
2 1
2 3
1 4
2
1 2
3 4
0 0
在这里插入图片描述
一开始是图中蓝色部分,其中1和4之间的边,2和3之间的边称之为桥,再加入12边后(绿色),桥还是那俩没变,再加入43边后,桥的数量为0(因为此时你去掉任何一个边,任意两个点都可连接)

题解:

题解借鉴:
题解一

题解二

本人对lca的讲解
我又感觉并查集可以做(虽然我并没有尝试)
Tarjan缩点问题
运行一次tarjan,求出桥和缩点,那么无向图将缩点组成一个数,树边就是原本的桥。我们想要得到一颗有根树,那我们就可以在执行tarjan的时候记录每一个点父节点和深度即可
每次连接两个点,如果两个点属于同一个缩点,那连接后不会产生影响,但如果不属于一个缩点的两点u和v,连接后,我们就要找这两个点的lca,即最小公共祖先(这也是我们要得到有根树的原因),这样u->lca(u,v)->v->u将连成一个环,而里面的树边也不再是桥,路径上的点都可以缩成一个点,即合成一个分量
对于缩点的处理:
缩点相当于在一个强连通分量里的点的集合,我们在实际操作中,有两个方法使用缩点
一个是:选取一个点为实点,其余点为虚点。实点即代表着这个分量的所有信息,虚点虽然属于这个分量的点,但可以直接无视。我们要做的,就是在这个分量里选择一个点,去代表整个分量。(相当于以一个代全部)
另一方法是:对每个点都设置一个归属集合,即表示这个点属于哪一个集合。在处理的过程中,一个集合可能又会被另一个集合所包含,所以我们可以利用并查集的路径压缩,很快地找到一个点的最终所属集合。(想当于一个整体)

代码:

方法一:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
#define ms(a,b) memset((a),(b),sizeof((a)))
using namespace std;
typedef long long LL;
const double EPS = 1e-8;
const int INF = 2e9;
const LL LNF = 2e18;
const int MAXN = 1e5+10;struct Edge
{int to, next;
}edge[MAXN*8];
int tot, head[MAXN];int index, dfn[MAXN], low[MAXN];
int isbridge[MAXN], sum_bridge;
int fa[MAXN], depth[MAXN];void addedge(int u, int v)
{edge[tot].to = v;edge[tot].next = head[u];head[u] = tot++;
}void Tarjan(int u, int pre)
{dfn[u] = low[u] = ++index;depth[u] = depth[pre] + 1;  //记录深度fa[u] = pre;        //记录父亲结点for(int i = head[u]; i!=-1; i = edge[i].next){int v = edge[i].to;if(v==pre) continue;if(!dfn[v]){Tarjan(v, u);low[u] = min(low[u], low[v]);if(low[v]>dfn[u])   //isbridge[v]表示在树中,以v为儿子结点的边是否为桥isbridge[v] = 1, sum_bridge++;}elselow[u] = min(low[u], dfn[v]);}
}void LCA(int u, int v)
{if(depth[u]<depth[v]) swap(u, v);while(depth[u]>depth[v])    //深度大的先往上爬。遇到桥,就把它删去。{if(isbridge[u]) sum_bridge--, isbridge[u] = 0;u = fa[u];}while(u!=v) //当深度一样时,一起爬。遇到桥,就把它删去。{if(isbridge[u]) sum_bridge--, isbridge[u] = 0;u = fa[u];if(isbridge[v]) sum_bridge--, isbridge[v] = 0;v = fa[v];}
}void init()
{tot = 0;memset(head, -1, sizeof(head));index = 0;memset(dfn, 0, sizeof(dfn));memset(low, 0, sizeof(low));memset(isbridge, 0, sizeof(isbridge));sum_bridge = 0;
}int main()
{int n, m, kase = 0;while(scanf("%d%d", &n, &m) && (n||m) ){init();for(int i = 1; i<=m; i++){int u, v;scanf("%d%d", &u, &v);addedge(u, v);addedge(v, u);}depth[1] = 0;Tarjan(1, 1);int q, a, b;scanf("%d", &q);printf("Case %d:\n", ++kase);while(q--){scanf("%d%d", &a, &b);LCA(a, b);printf("%d\n", sum_bridge);}printf("\n");}
}

方法二:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
#define ms(a,b) memset((a),(b),sizeof((a)))
using namespace std;
typedef long long LL;
const double EPS = 1e-8;
const int INF = 2e9;
const LL LNF = 2e18;
const int MAXN = 1e6+10;struct Edge
{int to, next;
}edge[MAXN], edge0[MAXN];   //edge为初始图, edge0为重建图
int tot, head[MAXN], tot0, head0[MAXN];int index, dfn[MAXN], low[MAXN];
int top, Stack[MAXN], instack[MAXN];
int belong[MAXN];
int fa[MAXN], depth[MAXN];  //fa用于重建图时记录当前节点的父亲节点,depth记录当前节点的深度
int sum_bridge;//找到x最终所属的结合
int find(int x) { return belong[x]==x?x:belong[x]=find(belong[x]); }void addedge(int u, int v, Edge edge[], int head[], int &tot)
{edge[tot].to = v;edge[tot].next = head[u];head[u] = tot++;
}void Tarjan(int u, int pre)
{dfn[u] = low[u] = ++index;Stack[top++] = u;instack[u] = true;for(int i = head[u]; i!=-1; i = edge[i].next){int v = edge[i].to;if(v==pre) continue;if(!dfn[v]){Tarjan(v, u);low[u] = min(low[u], low[v]);if(low[v]>dfn[u]) sum_bridge++;}else if(instack[v])low[u] = min(low[u], dfn[v]);}if(dfn[u]==low[u]){int v;do{v = Stack[--top];instack[v] = false;belong[v] = u;  //把集合的编号设为联通分量的第一个点}while(v!=u);}
}void build(int u, int pre)
{fa[u] = pre;    //记录父亲节点depth[u] = depth[pre] + 1;  //记录深度for(int i  = head0[u]; i!=-1; i=edge0[i].next)if(edge0[i].to!=pre)    //防止往回走build(edge0[i].to, u);
}int LCA(int u, int v)   //左一步右一步地找LCA
{if(u==v) return u;  //因为两个结点一定有LCA, 所以一定有u==v的时候//可能爬一步就爬了几个深度,因为中间的结点已经往上缩点了if(depth[u]<depth[v]) swap(u, v);   //深度大的往上爬sum_bridge--;int lca = LCA(find(fa[u]), v);return belong[u] = lca;     //找到了LCA,在沿路返回的时候把当前节点的所属集合置为LCA的所属集合
}void init()
{tot = tot0 = 0;memset(head, -1, sizeof(head));memset(head0, -1, sizeof(head0));index = top = 0;memset(dfn, 0, sizeof(dfn));memset(low, 0, sizeof(low));memset(instack, 0, sizeof(instack));sum_bridge = 0;
}int main()
{int n, m, kase = 0;while(scanf("%d%d", &n, &m) && (n||m) ){init();for(int i = 1; i<=m; i++){int u, v;scanf("%d%d", &u, &v);addedge(u, v, edge, head, tot);addedge(v, u, edge, head, tot);}Tarjan(1, 1);for(int u = 1; u<=n; u++)   //重建建图for(int i = head[u]; i!=-1; i = edge[i].next){int tmpu = find(u);int tmpv = find(edge[i].to);if(tmpu!=tmpv)addedge(tmpu, tmpv, edge0, head0, tot0);}depth[find(1)] = 0;build(find(1), find(1));    //把无根树转为有根树int q, a, b;scanf("%d", &q);printf("Case %d:\n", ++kase);while(q--){scanf("%d%d", &a, &b);LCA(find(a), find(b));printf("%d\n", sum_bridge);}printf("\n");}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/319983.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【树状数组】递增子序列(金牌导航 数据结构优化DP-1)

递增子序列 金牌导航 数据结构优化DP-1 题目大意 给出一个序列&#xff0c;让你求长度为m的单调递增子序列的个数 输入样例 3 2 1 1 2 7 3 1 7 3 5 9 4 8输出样例 2 12数据范围 1⩽n⩽104,1⩽m⩽100,0⩽ai⩽9876543211\leqslant n \leqslant 10^4,1\leqslant m \leqslant…

使用.NET Core 2.1的Azure WebJobs

WebJobs不是Azure和.NET中的新事物。 Visual Studio 2017中甚至还有一个默认的Azure WebJob模板&#xff0c;用于完整的.NET Framework。 但是&#xff0c;Visual Studio中以某种方式遗漏了.NET Core中WebJobs的类似模板。 在这篇文章中&#xff0c;我使用的是.NET Core 2.1来创…

P3265-[JLOI2015]装备购买【线性基,拟阵贪心】

正题 题目链接:https://www.luogu.com.cn/problem/P3265 题目大意 给出nnn个有权值的mmm元组。求最大独立集&#xff0c;即一个最大的集合且内部元素线性无关。且在集合最大的情况下权值和最小 通俗的说就是没有任何一个元素内被其他元素的倍数和表示。 解题思路 我们考虑线…

【决策单调性】玩具装箱(金牌导航 决策单调性优化DP-1)

玩具装箱 金牌导航 决策单调性优化DP-1 题目大意 给出若干个物品&#xff0c;把iii到jjj个物品装在一起的长度lj−i∑kijaklj-i\sum_{ki}^{j}a_klj−i∑kij​ak​&#xff08;物品必须是连续的&#xff09;&#xff0c;其代价为(lL)2(l L)^2(lL)2&#xff08;L为给出的常数…

HDU4612 Warm up

Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others) Total Submission(s): 11184 Accepted Submission(s): 2573HDU4612 Warm up 文章目录Problem Description题意&#xff1a;题解&#xff1a;代码&#xff1a;Problem Description N …

[NOIP2016 提高组] 天天爱跑步(树上差分)

如果没有时间的限制&#xff0c;这题就是对每个点iii&#xff0c;求经过iii的路径数&#xff0c;用树上差分解决即可&#xff1a; 枚举路径x→y{x\to y\{x→y{ a[x]1;a[y]1;a[x]1;a[y]1;a[x]1;a[y]1; a[lca(x,y)]−1;a[fa[lca(x,y)]]−2;a[lca(x,y)]-1;a[fa[lca(x,y)]]-2;a[lc…

.NET Core中的CSV解析库

感谢本篇首先特别感谢从此启程兄的《.NetCore外国一些高质量博客分享》, 发现很多国外的.NET Core技术博客资源, 我会不定期从中选择一些有意思的文章翻译总结一下。.NET Core中的CSV解析库本篇博客来源于.NET Core Totorials的《CSV Parsing In .NET Core》。背景介绍对于初级…

【manacher】双倍回文(金牌导航 manacher-2/luogu 4287)

双倍回文 金牌导航 manacher-2 luogu 4287 题目大意 设串为x&#xff0c;将其取反为x’&#xff0c;定义双倍回文为形如xx’xx’的串 现在给你一个字符串&#xff0c;让你求最大双倍回文子串 输入样例 16 ggabaabaabaaball输出样例 12数据范围 N⩽105N\leqslant 10^5N⩽…

P6178-[模板]Matrix-Tree 定理

正题 题目链接:https://www.luogu.com.cn/problem/P6178 题目大意 给出一个nnn个点mmm条边的无向/有向图。 求所有的生成树/以1为根的外向生成树的权值乘积和。 解题思路 矩阵AAA的行列式表示为det(A)det(A)det(A)&#xff0c;定义为 det(A)∑P(−1)μ(P)∏i1nAi,pidet(A)\…

可达性

来源&#xff1a;牛客网 文章目录题目描述题解&#xff1a;代码&#xff1a;时间限制&#xff1a;C/C 1秒&#xff0c;其他语言2秒 空间限制&#xff1a;C/C 262144K&#xff0c;其他语言524288K 64bit IO Format: %lld题目描述 给出一个 0 ≤ N ≤ 105 点数、0 ≤ M ≤ 105 边…

[集训队作业2018]小Z的礼物(min-max容斥,插头dp)

传送门 这种求 “取到所有物品的期望时间” 的题一般都用 min−maxmin-maxmin−max容斥 解决&#xff1a; 设t(i,j)t(i,j)t(i,j)为取到格子(i,j)(i,j)(i,j)的期望时间&#xff0c;集合S∪c(i,j)′∗′{t(i,j)}S\cup_{c(i,j)*}\{t(i,j)\}S∪c(i,j)′∗′​{t(i,j)} 那么根据min−…

为什么要使用Entity Framework

本文介绍从DDD(Domain-Driven Design[领域驱动设计])的角度来说说为什么要使用Entity Framework(以下都会简称为EF)&#xff0c;同时也看出类似Drapper之类的简陋ORM不足的地方。设想业务都是大家知晓的权限管理&#xff0c;实体类如下。读到这里&#xff0c;请先思考一下&…

【Splay】波动值之和(金牌导航 Splay-1)

波动值之和 金牌导航 Splay-1 题目大意 给出一个数列&#xff0c;求∑i1nminj1i−1∣ai−aj∣\sum_{i1}^{n}min_{j1}^{i-1}|a_i-a_j|∑i1n​minj1i−1​∣ai​−aj​∣ 输入样例 6 5 1 2 5 4 6输出样例 12样例解释 5∣1−5∣∣2−1∣∣5−5∣∣4−5∣∣6−5∣541011125|1…

P4336-[SHOI2016]黑暗前的幻想乡【矩阵树定理,容斥】

正题 题目链接:https://www.luogu.com.cn/problem/P4336 题目大意 nnn个点&#xff0c;n−1n-1n−1个边集&#xff0c;求有多少种方案使得每个边集中恰好选出一条边使得这nnn个点连成一棵树。 解题思路 我们需要利用好n−1n-1n−1个边集这个性质&#xff0c;因为nnn很小&…

Tarjan算法

Tarjan算法可以应用在求解 强连通分量&#xff0c;缩点&#xff0c;桥&#xff0c;割点&#xff0c;双连通分量&#xff0c;LCA等 关于文章目录强连通分量代码题目tarjan求割点割点概念流程代码&#xff1a;求无向图的割边&#xff0f;桥理解&#xff1a;代码&#xff1a;强连通…

[集训队作业2018] 万圣节的积木(李超线段树)

传送门 设最底层为第1层&#xff0c;倒数第二层为第2层&#xff0c;以此类推。 发现若第111 ~ iii层构成的积木稳定&#xff0c;第111 ~ jjj (j>ij>ij>i)构成的积木也稳定&#xff0c; 那么第i1i1i1 ~ jjj层构成的积木一定也是稳定的。 所以我们只要找到所有的iii满…

Ocelot简易教程(一)之Ocelot是什么

简单的说Ocelot是一个用.NET Core实现并且开源的API网关技术。可能你又要问了&#xff0c;什么是API网关技术呢&#xff1f;Ocelot又有什么特别呢&#xff1f;我们又该如何集成到我们的asp.net core程序中呢&#xff1f;下面我会通过一些列通俗易懂的教程来为大家讲解。今天的这…

P5516-[MtOI2019]小铃的烦恼【期望dp,线性消元】

正题 题目链接:https://www.luogu.com.cn/problem/P5516 题目大意 nnn个字母的一个字符串&#xff0c;每次随机选取两个不同的位置(x,y)(x,y)(x,y)让第xxx个位置的字符变成第yyy个位置的字符。 求期望多少次能够把所有字符变成同一个。 解题思路 因为最终状态很多&#xff0…

如何在你的项目中集成 CAP【手把手视频教程】

前言之前录制过一期关于CAP的视频&#xff0c;但是由于当时是直播时录制的视频&#xff0c;背景音比较杂所以质量有点差。这次的视频没有直播&#xff0c;直接录制的&#xff0c;视频质量会好很多&#xff0c;第一遍录制完成之后发现播放到一半没有声音&#xff0c;所以又重新录…

【Splay】文艺平衡树(金牌导航 Splay-2)

#文艺平衡树 金牌导航 Splay-2 题目大意 给你一个1~n的序列&#xff0c;然后对序列的区间做若干次翻转&#xff0c;问你最后的序列 输入样例 5 3 1 3 1 3 1 4输出样例 4 3 2 1 5数据范围 1⩽n,m⩽105,1⩽l⩽r⩽n1\leqslant n,m\leqslant 10^5,1\leqslant l\leqslant r \l…