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,一经查实,立即删除!

相关文章

使用.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来创…

.NET Core中的CSV解析库

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

为什么要使用Entity Framework

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

Tarjan算法

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

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

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

如何在你的项目中集成 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…

.net core实践系列之短信服务-Sikiro.SMS.Api服务的实现

前言本篇会继续讲解Sikiro.SMS.Job服务的实现&#xff0c;在我写第一篇的时候&#xff0c;我就发现我当时设计的架构里Sikiro.SMS.Job这个可以选择不需要&#xff0c;而使用MQ代替。但是为了说明调度任务使用实现也坚持写了下。后面会一篇针对架构、实现优化的讲解。源码地址&a…

Drainage Ditches POJ1273

Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 93263 Accepted: 36174试题链接 文章目录Description题意&#xff1a;题解&#xff1a;代码&#xff1a;Dinic做法EK做法Description Every time it rains on Farmer John’s fields, a pond forms over Bessie’…

P2756 飞行员配对方案问题【网络流24题】

P2756 飞行员配对方案问题 文章目录题目背景题解&#xff1a;代码&#xff1a;题目背景 第二次世界大战期间&#xff0c;英国皇家空军从沦陷国征募了大量外籍飞行员。由皇家空军派出的每一架飞机都需要配备在航行技能和语言上能互相配合的两名飞行员&#xff0c;其中一名是英国…

大数据分析中使用关系型数据库的关键点

相当一部分大数据分析处理的原始数据来自关系型数据库&#xff0c;处理结果也存放在关系型数据库中。原因在于超过99%的软件系统采用传统的关系型数据库&#xff0c;大家对它们很熟悉&#xff0c;用起来得心应手。在我们正式的大数据团队&#xff0c;数仓&#xff08;数据仓库H…

图论复习——最小生成树MST

知识点 MST的构造 Boruvka算法常用于解决这类问题&#xff1a;给你n个点&#xff0c;每个点有点权&#xff0c;任意两个点之间有边权&#xff0c;边权为两个点权用过某种计算方式得出&#xff0c;求最小生成树。动图 MST上的确定性和存在性问题 最小生成树的两个性质&#xf…

Ocelot简易教程(二)之快速开始1

Ocelot是为.net core量身定做的&#xff0c;目前是基于 netstandard2.0进行构建的。.NET Core 2.1中如何使用呢&#xff1f;安装NuGet package使用nuget安装Ocelot及其依赖项。您需要创建一个netstandard2.0项目并将其Package安装到项目中。然后按照下面的“启动”和“ 配置”节…

P2761 软件补丁问题

文章目录题目描述题解&#xff1a;代码&#xff1a;添加链接描述题目描述 T 公司发现其研制的一个软件中有 n 个错误&#xff0c;随即为该软件发放了一批共 m 个补丁程序。每一个补丁程序都有其特定的适用环境&#xff0c;某个补丁只有在软件中包含某些错误而同时又不包含另一些…

Xamarin中国技术社区及BXUG官网上线啦

Xamarin中国技术社区及BXUG官网为.NET开发者提供移动跨平台技术学习的园地&#xff0c;为Xamarin及.NET技术达人提供展示分享的舞台&#xff0c; 为企业CTO等技术负责人提供跨平台移动应用解决方案的交流平台&#xff01;网址链接&#xff1a;http://bxug.bopoda.cn/Xamarin中国…

用python将图片转换成二值图像

大创项目是图像识别&#xff0c;第一个任务是将一个图片转换成二值图像 之前用过python的numpy和turtle&#xff0c;这次要用到图像库PIL的类Image&#xff0c;也算是刚刚从零开始学起 整体效果&#xff08;用01串表示图像&#xff09; 原理很简单&#xff1a;将图片中黑色…

.Net Core SignalR 初体验

前言Asp.Net SignalR已经出来很久了&#xff0c;但是一直没有静下心来好好看看。昨天花了几个小时的时间看了下。首先借鉴了官方文档&#xff0c;如何搭建一个SignalR的Demo。参考文章&#xff1a;https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/signalr?viewaspnet…

CF1251F-Red-White Fence【NTT】

前言 刚开始看错题推了半天的生成函数 正题 题目链接:https://www.luogu.com.cn/problem/CF1251F 题目大意 nnn个白色木板&#xff0c;kkk个红色木板&#xff0c;给出这些木板的高度&#xff0c;木板排成一排形成栅栏。栅栏要求只有一个红色木板且在红色木板左边单调升&…

图论复习——dfs树,点双,边双,强连通分量

知识点 dfs树 对一个图运行 dfs 算法&#xff0c;每个点uuu的父亲定义为第一次遍历uuu时的前驱结点&#xff0c;若无则为根。 无向图的 dfs树 没有横叉边。 有向图的 dfs树 横叉边方向唯一&#xff0c;总是从后访问的点指向先访问的点。 dfs树详解 tarjan 点双 定义&#…

【点分治】Tree(luogu 4178/金牌导航 点分治-1)

Tree luogu 4178 金牌导航 点分治-1 题目大意 给出一棵树&#xff0c;问你书中路径长度小于等于k的点对个数有多少个 输入样例 5 1 2 3 1 3 1 1 4 2 3 5 1 4输出样例 8数据范围 1⩽N⩽41041\leqslant N \leqslant 4\times 10^41⩽N⩽4104 解题思路 对于该树&#xff0…