Network

Time Limit: 5000MS   Memory Limit: 65536K
Total Submissions: 10371   Accepted: 3853

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

Source

 

割边:在连通图中,删除了连通图的某条边后,图不再连通。这样的边被称为割边,也叫做桥。
割点:在连通图中,删除了连通图的某个点以及与这个点相连的边后,图不再连通。这样的点被称为割点。
DFS搜索树:用DFS对图进行遍历时,按照遍历次序的不同,我们可以得到一棵DFS搜索树。

树边:在搜索树中的蓝色线所示,可理解为在DFS过程中访问未访问节点时所经过的边,也称为父子边
回边:在搜索树中的橙色线所示,可理解为在DFS过程中遇到已访问节点时所经过的边,也称为返祖边、后向边
观察DFS搜索树,我们可以发现有两类节点可以成为割点。对根节点u,若其有两棵或两棵以上的子树,则该根结点u为割点;对非叶子节点u(非根节点),若其中的某棵子树的节点均没有指向u的祖先节点的回边,说明删除u之后,根结点与该棵子树的节点不再连通;则节点u为割点。对于根结点,显然很好处理;但是对于非叶子节点,怎么去判断有没有回边是一个值得深思的问题。我们用dfn[u]记录节点u在DFS过程中被遍历到的次序号,low[u]记录节点u或u的子树通过非父子边追溯到最早的祖先节点(即DFS次序号最小),那么low[u]的计算过程如下。

对于给的例子,其求出的dfn和low数组如下。
id     123456
dfn   123456
low   111444
可以发现,对于情况2,当(u,v)为树边且low[v]≥dfn[u]时,节点u才为割点。而当(u,v)为树边且low[v]>dfn[u]时,表示v节点只能通过该边(u,v)与u连通,那么(u,v)即为割边。tarjan算法的时间复杂度是O(n+m)的,非常快。

题意:给出一幅无向图,然后进行加边,每加一条边,询问图中割边的数量

思路:每次加边,把u-v-lca(u,v)-u这个环上的割边减掉。

 
 //2017-08-20
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm> using namespace std; const int N = ;
const int M = ;
int head[N], tot;
struct Edge{
int to, next;
}edge[M<<]; void init(){
tot = ;
memset(head, -, sizeof(head));
} void add_edge(int u, int v){
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++; edge[tot].to = u;
edge[tot].next = head[v];
head[v] = tot++;
} int n, m, deep, ans;
int dfn[N];//dfn[u]记录节点u在DFS过程中被遍历到的次序号
int low[N]; //low[u]记录节点u或u的子树通过非父子边追溯到最早的祖先节点(即DFS次序号最小)
int fa[N];//保存dfs树的信息
int level[N];//记录节点在dfs树中的深度
int bridge[N];//记录割边,若bridge[u] == 1, 则<u, fa[u]>为一条割边 void tarjan(int u, int father){
fa[u] = father;
dfn[u] = low[u] = deep++;
level[u] = level[father]+;
for(int i = head[u]; i != -; i = edge[i].next){
int v = edge[i].to;
if(dfn[v] == -){
tarjan(v, u);
low[u] = min(low[u], low[v]);
if(low[v] > dfn[u]){
bridge[v] = ;
ans++;
}
}else if(v != father)
low[u] = min(low[u], dfn[v]);
}
} void lca(int a, int b){
while(level[a] > level[b]){
if(bridge[a]){
ans--;
bridge[a] = ;
}
a = fa[a];
}
while(level[b] > level[a]){
if(bridge[b]){
ans--;
bridge[b] = ;
}
b = fa[b];
}
while(a != b){
if(bridge[a]){
ans--;
bridge[a] = ;
}
if(bridge[b]){
ans--;
bridge[b] = ;
}
a = fa[a];
b = fa[b];
}
} int main()
{
//freopen("inputD.txt", "r", stdin);
int kase = ;
while(scanf("%d%d", &n, &m)!=EOF && (n || m)){
printf("Case %d:\n", ++kase);
init();
int u, v;
for(int i = ; i < m; i++){
scanf("%d%d", &u, &v);
add_edge(u, v);
}
memset(bridge, , sizeof(bridge));
memset(dfn, -, sizeof(dfn));
memset(low, , sizeof(low));
level[] = ;
deep = ;
tarjan(, );
int q;
scanf("%d", &q);
while(q--){
scanf("%d%d", &u, &v);
if(ans)lca(u, v);
printf("%d\n", ans);
}
printf("\n");
} return ;
}

POJ3694(KB9-D 割边+LCA)的更多相关文章

  1. poj 3694(割边+lca)

    题意:给你一个无向图,可能有重边,有q次询问,问你每次我添加一条边,添加后这个图还有多少个桥 解题思路:首先先把所有没有割边的点对缩成一个联通块,无向图一般并查集判环,然后就得到一个割边树,给你一条新 ...

  2. POJ 3694 Network(Tarjan求割边+LCA)

    Network Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 10969   Accepted: 4096 Descript ...

  3. POJ3694 Network(连通图+LCA)

    题目链接:http://poj.org/problem?id=3694 题目大意:给定一个图,每次添加一条边(可能有重边).输出每次添加后桥的 数目.由于添加边的次数比较多,添加一次Tarjin一次明 ...

  4. poj 3694 pku 3694 Network tarjan求割边 lca

    题意:给你一个连通图,然后再给你n个询问,每个询问给一个点u,v表示加上u,v之后又多少个桥.一个最容易想到的办法就是先加边找桥,加边找桥,这样可定超时.那么就可以缩点,因为如果一条边不是桥那么无论怎 ...

  5. poj 3694 Network(割边+lca)

    题目链接:http://poj.org/problem?id=3694 题意:一个无向图中本来有若干条桥,有Q个操作,每次加一条边(u,v),每次操作后输出桥的数目. 分析:通常的做法是:先求出该无向 ...

  6. POJ3694 Network【连通分量+LCA】

    题意: 一个无向图可以有重边,下面q个操作,每次在两个点间连接一条有向边,每次连接后整个无向图还剩下多少桥(注意是要考虑之前连了的边,每次回答是在上一次的基础之上). 思路: 首先运行一次Tarjan ...

  7. Network(POJ3694+边双连通分量+LCA)

    题目链接:http://poj.org/problem?id=3694 题目: 题意:给你一个n个点m条边的无向连通图,进行q次操作,每次操作在u和v之间加一条边,问每次操作之后“桥”的数量. 思路: ...

  8. poj3694 边-双连通分量+lca

    题意:先给了一张无向图,然后依次加边,每次求桥的数量 题解:先用一次tarjan,我们可以标记桥的位置和记录桥的数量同时记录fa数组,然后更新边的时候我们可以用lca,因为在tarjan缩点之后得到了 ...

  9. 【POJ 3694】 Network(割边&lt;桥&gt;+LCA)

    [POJ 3694] Network(割边+LCA) Network Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 7971 ...

随机推荐

  1. iOS-项目开发1-Block

    Block回顾 Block分为NSStackBlock, NSMallocBlock, NSGloblaBlock.即栈区Block,堆区Block,全局Block.在ARC常见的是堆块. 在ARC中 ...

  2. Docker - 基础讲义

    Docker Docker - 官网 Docker - Hub GitHub - Docker dockerinfo Docker中文社区 Docker入门教程 Docker从入门到实践 虚拟化技术 ...

  3. Smart/400开发上手3: 练习实践

    练习题 在2006年1月1日之前入职且在职的营销员,给予年资补贴2000元: 符合以上条件的,再按以下标准一次性发放职级补贴: 职级代码 简称 补偿金额 A1 AD 6000 B1 SBM 5000 ...

  4. 【sping揭秘】4、某些无法注册到IOC容器的对象如何交给spring托管

    可以实现spring的factoryBean 接口,这样可以加入spring的IOC容器 比如现在有一个类叫MyObject,我们没有这个对象的源码,无法对这个对象进行操作,那么我们如何加入sprin ...

  5. POJ 2487

    #include<iostream> #include<stdio.h> using namespace std; int compare(void const * i,voi ...

  6. 本地主机不安装oracle客户端--访问远程oracle数据库

    在不安装oracle客户端情况下用sqlplus连接数据库: 1.去官网下载 http://www.oracle.com/technetwork/topics/winx64soft-089540.ht ...

  7. Java获取随机数获取制定范围指定个数不重复的随机数

    一.JDK中提供的两种方式 1.Math类中的random()方法public static double random()返回带正号的 double 值,该值大于等于 0.0 且小于 1.0 [0. ...

  8. Spring的JavaMail实现异步发送邮件

    具体背景就不说了,可以网上搜索相关知识,或者直接看Sping MailSender的官坊网页.这里就直接实战了(Java实现异步发送电子邮件,包含中文无乱码). Maven: <dependen ...

  9. wordpress添加文章阅读数量

    将下面代码添加到functions.php //取得文章的阅读次数 function post_views($before = '点击 ', $after = ' 次', $echo = 1) { g ...

  10. koa2 接收post参数

    koa2接收Post参数由于没有在上下文对象上解析,所以需要用node 原生req解析. 获取到的参数,要注意转码问题. const Koa = require('koa'); const app = ...