POJ 3694 tarjan 桥+lca

Network

Time Limit: 5000MS   Memory Limit: 65536K
Total Submissions: 7298   Accepted: 2651

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

2008 Asia Hefei Regional Contest Online by USTC

题目意思:

n个节点,m条无向边的图。然后q个操作,每个操作连接u、v点,然后输出连接后图中剩余桥的个数。

思路:

先tarjan标记一下桥,然后lca把路径上所有桥去掉标记。

代码:

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 #include <iostream>
  5 #include <vector>
  6 #include <queue>
  7 #include <cmath>
  8 #include <set>
  9 #include <map>
 10 #include <stack>
 11 using namespace std;
 12
 13 #define N 100005
 14
 15 int n, m;
 16 int dfn[N], low[N], Time;
 17 int dep[N];
 18 bool brg[N];
 19 int father[N];
 20 int brg_num;
 21
 22 struct Edge{
 23     int u, v, next;
 24 }e[400005];
 25
 26 int cnt;
 27 int head[N];
 28
 29 void setEdge(int u,int v){
 30     e[cnt].u=u;e[cnt].v=v;
 31     e[cnt].next=head[u];head[u]=cnt++;
 32 }
 33
 34 void tarjan(int u,int fa){
 35     int i, v;
 36     dfn[u]=low[u]=Time++;
 37     for(i=head[u];i!=-1;i=e[i].next){
 38         v=e[i].v;
 39         if(v==fa) continue;
 40         if(!dfn[v]){
 41             dep[v]=dep[u]+1;
 42             father[v]=u;
 43             tarjan(v,u);
 44             if(low[v]>dfn[u]){
 45                 brg_num++;
 46                 brg[v]=true;
 47             }
 48             low[u]=min(low[u],low[v]);
 49         }
 50         else low[u]=min(dfn[v],low[u]);
 51     }
 52 }
 53
 54 void lca(int u,int v){
 55     while(dep[u]>dep[v]){
 56         if(brg[u]) {
 57             brg[u]=false,brg_num--;
 58         }
 59         u=father[u];
 60     }
 61     while(dep[v]>dep[u]){
 62         if(brg[v]) {
 63             brg[v]=false,brg_num--;
 64         }
 65         v=father[v];
 66     }
 67     while(u!=v){
 68         if(brg[u]) {
 69             brg[u]=false,brg_num--;
 70         }
 71         u=father[u];
 72         if(brg[v]) {
 73             brg[v]=false,brg_num--;
 74         }
 75         v=father[v];
 76     }
 77 }
 78
 79 main()
 80 {
 81     int i, j, k;
 82     int u, v;
 83     int kase=1;
 84     while(scanf("%d %d",&n,&m)==2){
 85         if(!n&&!m) break;
 86         memset(head,-1,sizeof(head));
 87         cnt=0;
 88         for(i=0;i<m;i++){
 89             scanf("%d %d",&u,&v);
 90             setEdge(u,v);
 91             setEdge(v,u);
 92         }
 93         Time=1;
 94         memset(dfn,0,sizeof(dfn));
 95         memset(brg,false,sizeof(brg));
 96         brg_num=0;
 97         for(i=1;i<=n;i++){
 98             if(!dfn[i]){
 99                 dep[i]=0;
100                 tarjan(i,i);
101             }
102         }
103         printf("Case %d:\n",kase++);
104         int q;
105         scanf("%d",&q);
106         for(i=0;i<q;i++){
107             scanf("%d %d",&u,&v);
108             lca(u,v);
109             printf("%d\n",brg_num);
110         }
111         cout<<endl;
112     }
113 }
时间: 2024-12-07 11:11:15

POJ 3694 tarjan 桥+lca的相关文章

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 强连通分量+LCA

点击打开链接 题意:给一个图,然后依次加进去边,问每次加过边后还有几个桥,之前加入的会影响后面加入的 思路:先将图的桥全部找出来,然后将桥的点标记上,然后不需要缩点,直接进行裸的LCA,再找最近公共祖先的时候,遇到标记的点将结果减1,然后将标记取消,不知道为什么我写的跑的特别慢,别人写的都很快,有神犇知道求指教 #include <vector> #include <stdio.h> #include <stdlib.h> #include <string.h&g

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

Tarjan算法各种&amp;RMQ&amp; POJ 3694

关于tarjan 的思想可以在网上搜到,具体我也不太清楚,应该说自己理解也不深,下面是做题经验得到的一些模板. 其中有很多转载,包括BYVoid等,感谢让我转...望各路大神愿谅 有向图求连通分量的一般方法: 1 void Tarjan(u) { 2 dfn[u]=low[u]=++index 3 stack.push(u) 4 for each (u, v) in E { 5 if (v is not visted) { 6 tarjan(v) 7 low[u] = min(low[u], l

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

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

poj 1470 Closest Common Ancestors tarjan求lca和树的孩子兄弟表示

题意: 给一棵树和若干查询点对,求这些点对的lca. 分析: tarjan求lca的模板题,树还是用孩子兄弟表示法比较简洁. 代码: //poj 1470 //sepNINE #include <iostream> #include <vector> using namespace std; const int maxN=1024; int n,u,v,t,m,x,y;; int par[maxN],son[maxN],bro[maxN],f[maxN],cnt[maxN],vis

【最近公共祖先Tarjan】Tarjan求LCA练习

Tarjan求LCA 这是一篇非常好的讲解,靠这个文章搞懂的~ 1 void tarjan(int u) 2 { 3 vis[u]=1; 4 for(int i=0;i<edge[u].size();i++) 5 { 6 int v=edge[u][i]; 7 if(vis[v] == 0) 8 { 9 tarjan(v); 10 p[v]=u; 11 } 12 } 13 for(int i=0;i<qy[u].size();i++) 14 { 15 int v=qy[u][i].v,id=q

POJ 1330 裸的LCA

Nearest Common Ancestors Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 17720   Accepted: 9393 Description A rooted tree is a well-known data structure in computer science and engineering. An example is shown below:  In the figure, each

POJ 1986 Distance Queries LCA树上两点的距离

题目来源:POJ 1986 Distance Queries 题意:给你一颗树 q次询问 每次询问你两点之间的距离 思路:对于2点 u v dis(u,v) = dis(root,u) + dis(root,v) - 2*dis(roor,LCA(u,v)) 求最近公共祖先和dis数组 #include <cstdio> #include <cstring> #include <vector> using namespace std; const int maxn =