POJ 3694 Network

Network

Time Limit: 5000ms

Memory Limit: 65536KB

This problem will be judged on PKU. Original ID: 3694
64-bit integer IO format: %lld      Java class name: Main

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

2008 Asia Hefei Regional Contest Online by USTC

解题:边双连通+LCA

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 using namespace std;
 5 const int maxn = 100010;
 6 struct arc {
 7     int to,next;
 8     arc(int x = 0,int y = -1) {
 9         to = x;
10         next = y;
11     }
12 } e[maxn<<2];
13 int head[maxn],low[maxn],dfn[maxn],p[maxn];
14 int tot,ans,idx,n,m,q,uf[maxn];
15 void add(int u,int v) {
16     e[tot] = arc(v,head[u]);
17     head[u] = tot++;
18     e[tot] = arc(u,head[v]);
19     head[v] = tot++;
20 }
21 int Find(int x) {
22     return uf[x] = x == uf[x]?x:Find(uf[x]);
23 }
24 bool Union(int x,int y) {
25     int fx = Find(x);
26     int fy = Find(y);
27     if(fx != fy) uf[fx] = fy;
28     return fx != fy;
29 }
30 void tarjan(int u,int fa) {
31     dfn[u] = low[u] = ++idx;
32     bool flag = true;
33     for(int i = head[u]; ~i; i = e[i].next) {
34         if(e[i].to == fa && flag) {
35             flag = false;
36             continue;
37         }
38         if(!dfn[e[i].to]) {
39             tarjan(e[i].to,u);
40             p[e[i].to] = u;
41             low[u] = min(low[u],low[e[i].to]);
42             if(low[e[i].to] > dfn[u]) ans++;
43             else Union(u,e[i].to);
44         } else if(e[i].to != fa) low[u] = min(low[u],dfn[e[i].to]);
45     }
46 }
47 void LCA(int x,int y){
48     while(x != y){
49         while(dfn[x] >= dfn[y] && x != y){
50             ans -= Union(x,p[x]);
51             x = p[x];
52         }
53         while(dfn[y] >= dfn[x] && x != y){
54             ans -= Union(y,p[y]);
55             y = p[y];
56         }
57     }
58 }
59 void init(){
60     for(int i = 0; i < maxn; ++i){
61         head[i] = -1;
62         low[i] = dfn[i] = 0;
63         p[i] = 0;
64         uf[i] = i;
65     }
66     ans = idx = tot = 0;
67 }
68 int main() {
69     int u,v,cs = 1;
70     while(scanf("%d %d",&n,&m),n||m){
71         init();
72         for(int i = 0; i < m; ++i){
73             scanf("%d %d",&u,&v);
74             add(u,v);
75         }
76         tarjan(1,-1);
77         scanf("%d",&q);
78         printf("Case %d:\n",cs++);
79         while(q--){
80             scanf("%d %d",&u,&v);
81             if(Find(u) != Find(v)) LCA(u,v);
82             printf("%d\n",ans);
83         }
84         puts("");
85     }
86     return 0;
87 }

时间: 2024-10-26 13:28:07

POJ 3694 Network的相关文章

Poj 3694 Network (连通图缩点+LCA+并查集)

题目链接: Poj 3694 Network 题目描述: 给出一个无向连通图,加入一系列边指定的后,问还剩下多少个桥? 解题思路: 先求出图的双连通分支,然后缩点重新建图,加入一个指定的边后,求出这条边两个端点根节点的LCA,统计其中的桥,然后把这个环中的节点加到一个集合中,根节点标记为LCA. 题目不难,坑在了数组初始化和大小 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #inclu

POJ 3694——Network——————【连通图,LCA求桥】

Network Time Limit:5000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit Status Practice POJ 3694 Description A network administrator manages a large network. The network consists of N computers and M links between pairs of compute

poj 3694 Network (桥入门)

1 /******************************************** 2 Network(POJ 3694) 3 http://poj.org/problem?id=3694 4 桥入门题 + LCA(树中最小公共祖先) 5 做这题必须要会用邻接表(做这题才学会),因为 6 给的边有重边,用vector不好记录重边. 7 8 ********************************************/ 9 10 #include<iostream> 11

POJ 3694 Network (tarjan + LCA)

题目链接:http://poj.org/problem?id=3694 题意是给你一个无向图n个点,m条边,将m条边连接起来之后形成一个图,有Q个询问,问将u和v连接起来后图中还有多少个桥. 首先用tarjan标记点的low和dfn值,那么u和v相连的边是桥的条件是dfn[u] < low[v](说明v与u不在一个连通分量里面,v无法通过回溯到达u点,画个图模拟会清楚).那么bridge[v]++表示u与v相连的边是桥(若是标记bridge[u]++,则最后的答案可能会出错,亲测).要是u和v相

[双连通分量] POJ 3694 Network

Network Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 9434   Accepted: 3511 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

POJ 3694 Network ——(桥 + LCA)

题意:给n个点和m条边,再给出q条边,问每次加一条边以后剩下多少桥. 分析:这题是结合了LCA和dfn的妙用._dfn数组和dfn的意义不一样,并非访问的时间戳,_dfn表示的是被访问的顺序,而且是多线程访问下的顺序,举个例子,同一个点分岔开来的点,距离这个点相同距离的点,他们的_dfn的值是相同的,而dfn不是,类似于单线程dfs访问的各点的dfn值是不同的. 具体见代码: 1 #include <stdio.h> 2 #include <algorithm> 3 #includ

poj 3694 Network(桥+lca)

给定一个无向无环图,保证连通,求每加入一条给定的边图中还剩下多少桥. 双联通缩点重新建图后,再用lca在线算法解. lca算法参考斌神http://www.cnblogs.com/kuangbin/p/3184884.html 这个版本的lca思路大致是先topsort,再用并查集分别从查询的两点向根节点回溯,直到两个点碰撞.效率我分析不出来,但看得出效率很高,每次查询都对后面查询做了工作. 代码: #include<iostream> #include<cstdio> #incl

POJ 3694 Network(无向图求桥+重边处理+LCA)

题目大意: 给你一个无向图,然后再给你一个Q代表有Q次询问,每一次加一条边之后还有几座桥.在这里要对重边进行处理. 每次加入一条边之后,在这条搜索树上两个点的公共祖先都上所有点的桥都没了. 这里重边的处理上要说一下, 我以前第一写的时候根本没考虑这个问题,但是居然过了...过了...  很扯淡,但是重边的问题确实是存在. 这里我们 使用一个 bridge 数组来保存桥, 因为有重边的存在  只有 bridge 数量为 1 的时候这个路径才算是桥,否则则不是桥 bridge[i] 是指  i 和

POJ - 3694 Network(tarjan+lca)

题意:给出一个无相图,然后q次新增加边,问在添加边的过程中桥的数目当且仅当无向边(u,v)为树枝的时候,需要满足dfn(u)<low(v),也就是v向上翻不到u及其以上的点,那么u-v之间一定能够有1条或者多条边不能删去,因为他们之间有一部分无环,是桥思路:首先我们知道在给定一张图之后,不断添加边,桥的数目只会减少而不是增加tarjan的使用就是缩点,将一个连通分量缩成一个点,那么那个连通分量中的边都不会是桥同时缩完点之后我们就会发现,桥其实就是新形成的树的边在添加的过程中,如果是在连通分量内就