无向连通图求割边+缩点+LCA
| Time Limit: 5000MS | Memory Limit: 65536K | |
| Total Submissions: 7082 | Accepted: 2555 |
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次询问,每次询问u和v,代表把u和v连接之后此时的图还有多少个桥,(加上的边不在去掉)
分析:如果每次询问加入边之后都进行一次tarjan则会超时,可以先按照桥缩点成一棵树,原来的桥是现在的树的边,每次加入一条边<u,v>之后,把u和v进行LCA,标记一下此时有多少路径被标记,则此时的桥的个数是num-sum;
#include"cstdio"
#include"cstring"
#include"cstdlib"
#include"cmath"
#include"string"
#include"map"
#include"cstring"
#include"iostream"
#include"algorithm"
#include"queue"
#include"stack"
#define inf 0x3f3f3f3f
#define M 100009
#define eps 1e-8
#define INT int
using namespace std;
struct node
{
int u,v,next;
}edge[M*10],e[M*10];
stack<int>q;
int t,head[M],dfn[M],low[M],indx,cut[M*10],num,cnt,belong[M],use[M],suo[M],mark[M*10],pre[M],pp[M],ranks[M],ans;
void init()
{
t=0;
memset(head,-1,sizeof(head));
}
void add(int u,int v)
{
edge[t].u=u;
edge[t].v=v;
edge[t].next=head[u];
head[u]=t++;
}
void tarjan(int u,int id)//求桥
{
dfn[u]=low[u]=++indx;
q.push(u);
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
if(id==(i^1))continue;
if(!dfn[v])
{
tarjan(v,i);
low[u]=min(low[u],low[v]);
if(low[v]>dfn[u])
{
cut[++num]=i;
mark[i]=mark[i^1]=1;//存桥的编号,且把其进行标记
} }
else
low[u]=min(low[u],dfn[v]);
}
}
void slove(int n)
{
num=indx=0;
memset(low,0,sizeof(low));
memset(dfn,0,sizeof(dfn));
memset(cut,0,sizeof(cut));
memset(mark,0,sizeof(mark));
for(int i=1;i<=n;i++)
{
if(!dfn[i])
tarjan(i,-1);
}
return ;
}
void dfs(int u,int tep)
{
use[u]=1;
suo[u]=tep;
for(int i=head[u];~i;i=edge[i].next)
{
if(mark[i])continue;
int v=edge[i].v;
if(!use[v])
dfs(v,tep);
}
}
void DFS(int u,int fa)
{
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
if(fa==v)continue;
pre[v]=u;
ranks[v]=ranks[u]+1;
DFS(v,u);
}
}
void LCA(int u,int v)
{
while(u!=v)
{
if(ranks[u]>ranks[v])
{
if(!pp[u])
{
ans++;
pp[u]=1;
}
u=pre[u];
}
else
{
if(!pp[v])
{
pp[v]=1;
ans++;
}
v=pre[v];
}
} }
void litter(int n)
{
cnt=0;
memset(suo,0,sizeof(suo));
memset(use,0,sizeof(use));
for(int i=1;i<=num;i++)//缩点
{
int u=edge[cut[i]].u;
if(!suo[u])
{
dfs(u,++cnt);
}
int v=edge[cut[i]].v;
if(!suo[v])
dfs(v,++cnt);
e[i].u=u;
e[i].v=v;
}
// for(int i=1;i<=n;i++)
//printf("%d %d\n",i,suo[i]);
init();
for(int i=1;i<=num;i++)
{
int u=e[i].u;
int v=e[i].v;
add(suo[u],suo[v]);
add(suo[v],suo[u]);
}//把缩点后的图建成一棵树
memset(pre,-1,sizeof(pre));
ranks[1]=1;
DFS(1,1);
int Q;
cin>>Q;
int sum=0;
memset(pp,0,sizeof(pp));
while(Q--)
{
int a,b;
scanf("%d%d",&a,&b);
ans=0;
LCA(suo[a],suo[b]);
sum+=ans;
printf("%d\n",num-sum);
}
printf("\n"); }
int main()
{
int n,m,a,b,kk=1;
while(scanf("%d%d",&n,&m),n||m)
{
init();
for(int i=0;i<m;i++)
{
scanf("%d%d",&a,&b);
add(a,b);
add(b,a);
}
slove(n);
printf("Case %d:\n",kk++);
litter(n); }
return 0;
}
无向连通图求割边+缩点+LCA的更多相关文章
- ZOJ 2588 Burning Bridges(无向连通图求割边)
题目地址:ZOJ 2588 由于数组开小了而TLE了..这题就是一个求无向连通图最小割边.仅仅要推断dfn[u]是否<low[v],由于low指的当前所能回到的祖先的最小标号,增加low[v]大 ...
- 无向连通图求割边(桥)hdu4738,hdu3849
点击打开链接 题目链接: hdu 4738 题目大意: 曹操有N个岛,这些岛用M座桥连接起来 每座桥有士兵把守(也可能没有) 周瑜想让这N个岛不连通,但只能炸掉一座桥 并且炸掉一座桥需要派出不 ...
- ZOJ2588:Burning Bridges(无向连通图求割边)
题目:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1588 吐下槽,不得不说ZOJ好坑,模版题做了一个多小时. 题意:* ...
- ZOJ 2588 Burning Bridges(求含重边的无向连通图的割边) - from lanshui_Yang
Burning Bridges Time Limit: 5 Seconds Memory Limit: 32768 KB Ferry Kingdom is a nice little country ...
- poj3694+hdu2460 求桥+缩点+LCA/tarjan
这个题使我更深理解了TARJAN算法,题意:无向图,每添加一条边后文桥的数量,三种解法:(按时间顺序),1,暴力,每每求桥,听说这样能过,我没过,用的hash判重,这次有俩个参数(n->10w, ...
- 无向连通图求割点(tarjan算法去掉改割点剩下的联通分量数目)
poj2117 Electricity Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 3603 Accepted: 12 ...
- POJ1523:SPF(无向连通图求割点)
题目:http://poj.org/problem?id=1523 题目解析: 注意题目输入输入,防止PE,题目就是求割点,并问割点将这个连通图分成了几个子图,算是模版题吧. #include < ...
- POJ1144:Network(无向连通图求割点)
题目:http://poj.org/problem?id=1144 求割点.判断一个点是否是割点有两种判断情况: 如果u为割点,当且仅当满足下面的1条 1.如果u为树根,那么u必须有多于1棵子树 2. ...
- Poj 3694 Network (连通图缩点+LCA+并查集)
题目链接: Poj 3694 Network 题目描述: 给出一个无向连通图,加入一系列边指定的后,问还剩下多少个桥? 解题思路: 先求出图的双连通分支,然后缩点重新建图,加入一个指定的边后,求出这条 ...
随机推荐
- 让Storm插上CEP的翅膀 - Siddhi调研和集成
什么是 Siddhi? Siddhi 是一种 lightweight, easy-to-use, open source CEP(Complex Event Processing)引擎,由wso2公司 ...
- Web Storage事件无法触发
不管是在同源其他页面还是在本页面都不能触发storage事件. <!DOCTYPE html> <html> <head> <meta charset=&qu ...
- 搭建一个Flv视频播放服务器
搭建一个Flv视频播放服务器 热度 15已有 11511 次阅读2009-11-2 22:27 |关键词:服务器 视频 flv 播放 文档 错漏 经过一天的努力,查了好多资料,终于搞定了Flv视频服务 ...
- Spark学习笔记(一)
1.调度 分为FIFO和FAIR两种模式 创建调度池:sc.setLocalProperty("spark.scheduler.pool", "pool6") ...
- JDK核心包学习
StringBuffer 线程安全.可变字符序列 StringBuilder 非线程安全.可变字符序列,比StringBuffer更快 Boolean 使用valueOf产生Boolean实例 ...
- Delphi FindowWindow,FindowWindowEx
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms ...
- C#中Dynamic关键字
dynamic关键字和动态语言运行时(DLR)是.Net 4.0中新增的功能. 什么是"动态"? 编程语言有时可以划分为静态类型化语言和动态类型化语言.C#和Java经常被认为是静 ...
- JavaScript正则表达式(二)
定义 JavaScript种正则表达式有两种定义方式,定义一个匹配类似 <%XXX%> 的字符串 1. 构造函数 var reg=new RegExp('<%[^%>]+%&g ...
- mysql存储过程之游标遍历数据表
原文:mysql存储过程之游标遍历数据表 今天写一个mysql存储过程,根据自己的需求要遍历一个数据表,因为对存储过程用的不多,语法不甚熟悉,加之存储过程没有调试环境,花了不少时间才慢慢弄好,故留个痕 ...
- Insecure world writable dir /usr/local in PATH, mode 040777
/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/universal-darwin14/rbconfi ...