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
这个题啊!有点难度,一开始都只是想求出桥之后,再加入之后可能存在环,怎么办呢,后来才知道还有LCA这东西,当找到它们的LCA,把该路上的桥的去掉之后就是解了,那题目就简单了,求一次双连通,求一次LCA,不过我的程序跑了3000多ms,因为我求LCA是用普通的o(n)的算法,如果用o(lgn)的算法,那就不能求出答案咯,所以5000ms也真的是这个题的解法啊
#include<map> #include<set> #include<stack> #include<queue> #include<cmath> #include<vector> #include<cstdio> #include<string> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> #define inf 0x0f0f0f0f using namespace std; struct CUT_E { static const int maxn=100000+10; int low[maxn],pre[maxn],dfs_clock,n,m,sumcut,parent[maxn]; bool iscut[maxn]; vector<int>group[maxn]; void init() { for (int i=0;i<=n;i++) { group[i].clear(); pre[i]=0; iscut[i]=false; parent[i]=i; } sumcut=0; dfs_clock=0; } void addedge(int u,int v) { group[u].push_back(v); group[v].push_back(u); } int dfs(int u,int fa) { int lowu=pre[u]=++dfs_clock; for (int i=0;i<group[u].size();i++) { int v=group[u][i]; if (!pre[v]) { parent[v]=u; int lowv=dfs(v,u); lowu=min(lowu,lowv); if (lowv>pre[u]) {iscut[v]=true;sumcut++;} } else if (pre[v]<pre[u] && v!=fa) lowu=min(lowu,pre[v]); } low[u]=lowu; return lowu; } int get_sum() { int ans=dfs(-1,1); for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) //if (cut_edge[i][j]) sumcut++; return sumcut; } }network; int LCA(int a,int b) { if(network.pre[a]<network.pre[b]) swap(a,b); while (network.pre[a]>network.pre[b]) { if (network.iscut[a]) {network.sumcut--;network.iscut[a]=false;} a=network.parent[a]; } while (a!=b) { if (network.iscut[b]) {network.sumcut--;network.iscut[b]=false;} b=network.parent[b]; } return network.sumcut; } int main() { int x,y,q,k=0; while (scanf("%d%d",&network.n,&network.m)!=EOF && network.n && network.m) { k++; network.init(); for (int i=0;i<network.m;i++) { scanf("%d%d",&x,&y); network.addedge(x,y); } network.dfs(1,-1); scanf("%d",&q); printf("Case %d:\n",k); while (q--) { scanf("%d%d",&x,&y); int ans=LCA(x,y); printf("%d\n",ans); } } return 0; }