[POJ3694]Network(Tarjan,LCA)
[POJ3694]Network
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
0
Case 2:
2
0
题意
给定一张\(N\)个点\(M\)条边的无向连通图,然后执行\(Q\)次操作,每次向图中添加一条边,并且询问当前无向图中“桥”的数量。
核心知识:边双联通分量
先一遍\(tarjan\)把原图中的桥全部标记,然后\(dfs\)把各个边双联通分量建成树。
考虑到每次加边:
1.两端点在同一个边双联通分量中,对答案不造成影响。
2.两端点不在同一个边双联通分量,因为在树中,所以可以形成一个环,两个边双联通分量之间的路径不再是桥,在总答案中减去。
因为本题时间比较宽裕,所以我们暴力往上跳就可以过了,但是还可以用并查集优化,但是没有打出来,下次再填坑吧。。。
边双联通分量的求法
求出无向图中所有的桥,把桥“删除”,无向图会分成若干个联通块,每一个联通块就是一个边双联通分量。求边双联通分量的时间复杂度:\(O(n)\)。
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int read()
{
int x=0,w=1;char ch=getchar();
while(ch>'9'||ch<'0') {if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x*w;
}
const int N=100010;
int n,m,q,t,cnt=1,visnum,num,ans,a,b;
int head[2*N],dfn[N],low[N],fa[2*N],x[2*N],y[2*N],deep[2*N];
bool bridge[4*N],vis[N],dcc[N];
struct node{
int to,next;
}edge[8*N];
void add(int x,int y)
{
cnt++;edge[cnt].to=y;edge[cnt].next=head[x];head[x]=cnt;
}
int gfa(int x){if(fa[x]==x)return x;return fa[x]=gfa(fa[x]);}
void tarjan(int k,int last)
{
dfn[k]=low[k]=++visnum;
for(int i=head[k];i;i=edge[i].next)
{
int v=edge[i].to;
if(!dfn[v])
{
tarjan(v,i);low[k]=min(low[k],low[v]);
if(low[v]>dfn[k])
{
bridge[i]=bridge[i^1]=1;ans++;
}
}
else if(i!=(last^1))low[k]=min(low[k],dfn[v]);
}
}
void dfs1(int k)
{
vis[k]=1;fa[k]=num;
for(int i=head[k];i;i=edge[i].next)
{
int v=edge[i].to;if(vis[v]||bridge[i])continue;
dfs1(v);
}
}
void dfs2(int k,int f)
{
for(int i=head[k];i;i=edge[i].next)
{
int v=edge[i].to;if(v==f)continue;
deep[v]=deep[k]+1;fa[v]=k;dcc[v]=1;dfs2(v,k);
}
}
int jump(int xx,int yy)
{
int qwe=0;if(deep[xx]<deep[yy]) swap(xx,yy);
while(deep[xx]>deep[yy])
{
if(dcc[xx]) dcc[xx]=0,qwe++;xx=fa[xx];
}
if(xx==yy)return qwe;
while(xx!=yy)
{
if(dcc[xx]) dcc[xx]=0,qwe++;xx=fa[xx];
if(dcc[yy]) dcc[yy]=0,qwe++;yy=fa[yy];
}
return qwe;
}
int main()
{
while(1)
{
n=read();m=read();if(n==0)break;t++;num=n;
for(int i=1;i<=m;i++)
{
x[i]=read();y[i]=read();
add(x[i],y[i]);add(y[i],x[i]);
}
tarjan(1,0);
for(int i=1;i<=n;i++)
{
if(!vis[i]){num++;fa[num]=num;dfs1(i);}
}
for(int i=1;i<=m;i++)
{
int xx=gfa(x[i]),yy=gfa(y[i]);
if(xx!=yy) add(xx,yy),add(yy,xx);
}
deep[n+1]=1;dfs2(n+1,0);q=read();
printf("Case %d:\n",t);
for(int j=1;j<=q;j++)
{
a=read();b=read();
int xx=fa[a],yy=fa[b];
if(xx!=yy) ans-=jump(xx,yy);printf("%d\n",ans);
}
printf("\n");
}
}
[POJ3694]Network(Tarjan,LCA)的更多相关文章
- 【BZOJ4784】[ZJOI2017]仙人掌(Tarjan,动态规划)
[BZOJ4784][ZJOI2017]仙人掌(Tarjan,动态规划) 题面 BZOJ 洛谷 题解 显然如果原图不是仙人掌就无解. 如果原图是仙人掌,显然就是把环上的边给去掉,变成若干森林连边成为仙 ...
- 【BZOJ1093】[ZJOI2007]最大半联通子图(Tarjan,动态规划)
[BZOJ1093][ZJOI2007]最大半联通子图(Tarjan,动态规划) 题面 BZOJ 洛谷 洛谷的讨论里面有一个好看得多的题面 题解 显然强连通分量对于题目是没有任何影响的,直接缩点就好了 ...
- 【洛谷5008】逛庭院(Tarjan,贪心)
[洛谷5008]逛庭院(Tarjan,贪心) 题面 洛谷 题解 如果图是一个\(DAG\),我们可以任意选择若干个不是入度为\(0\)的点,然后把它们按照拓扑序倒序删掉,不难证明这样一定是合法的. 现 ...
- POJ 1236 Network of Schools(tarjan算法 + LCA)
这个题目网上有很多答案,代码也很像,不排除我的.大家的思路应该都是taijan求出割边,然后找两个点的LCA(最近公共祖先),这两个点和LCA以及其他点构成了一个环,我们判断这个环上的割边有几条,我们 ...
- SPOJ 3978 Distance Query(tarjan求LCA)
The traffic network in a country consists of N cities (labeled with integers from 1 to N) and N-1 ro ...
- HDU-3072-IntelligenceSystem(tarjan,贪心)
链接:https://vjudge.net/problem/HDU-3072 题意: 给你n个点,1个点到另一个点连接花费c,但是如果几个点可以相互可达,则这几个点连通花费为0. 求将整个图连通的最小 ...
- [Poj2349]Arctic Network(二分,最小生成树)
[Poj2349]Arctic Network Description 国防部(DND)要用无线网络连接北部几个哨所.两种不同的通信技术被用于建立网络:每一个哨所有一个无线电收发器,一些哨所将有一个卫 ...
- POJ 1144 Network(Tarjan求割点)
Network Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 12707 Accepted: 5835 Descript ...
- 【BZOJ1924】【SDOI2010】所驼门王的宝藏(Tarjan,SPFA)
题目描述 在宽广的非洲荒漠中,生活着一群勤劳勇敢的羊驼家族.被族人恭称为"先知"的Alpaca L. Sotomon是这个家族的领袖,外人也称其为"所驼门王". ...
随机推荐
- @ResponseBody返回4种数据格式的数据
1.返回一个键值对或者集合 前端JS请求: //返回值为map的形式 $(".name").blur(function(){ $.ajax({ type:"Post&qu ...
- 北风设计模式课程---最少知识原则(Least Knowledge Principle)
北风设计模式课程---最少知识原则(Least Knowledge Principle) 一.总结 一句话总结: 最少知识原则(Least Knowledge Principle),或者称迪米特法则( ...
- grep的用法,小技巧,模板中含有\t时:grep -P "^\t" file
linux中grep和find的用法区别 本文章详细的介绍了关于在linux中的grep和find两个命令的用法介绍,以及后面总结了它们两年用法区别哦. 先我们来介绍一下关于grep用法和一些小注意事 ...
- Redis安装启动,Redis Desktop Manager安装
Window 下安装下载地址:https://github.com/MSOpenTech/redis/releases.Redis 支持 32 位和 64 位.这个需要根据你系统平台的实际情况选择,这 ...
- tail()函数
与head()函数类似,默认是取dataframe中的最后五行. 函数源码: def tail(self, n=): """ Returns last n rows &q ...
- C#之委托(一)
1,什么是委托 简单来说,就是代码在恰当的时间执行一段操作.代码不需要操作的细节.举个例子,遗嘱为例.一般来说遗嘱是在某人去世之前写好,然后把它放发到一个安全的地方,去世之后然后律师会执行遗嘱中的指令 ...
- linux .bashrc文件修改和生效
linux .bashrc文件修改和生效 cd home ==>选择用户文件夹=>ll -la .bashrc 使用man bash命令查看到的联机帮助文件中的相关解释如下: ...
- 【ABAP系列】SAP ABAP 模拟做成像windows一样的计算器
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[MM系列]SAP ABAP 模拟做成像wind ...
- Java设计模式——建造者模式(创建型模式)
概述 建造者模式也称为生成器模式,是一种对象创建型模式,它可以将复杂对象的建造过程抽象出来(抽象类别),使这个抽象过程的不同实现方法可以构造出不同表现(属性)的对象. 建造者模式意在为重叠构造 ...
- 003--PowerDesigner创建索引与外键
PowerDesigner创建索引与外键 一.创建索引 双击Table->Columns->创建索引 Step1:双击Table Step2:选择Columns->创建索引 弹出如下 ...