Time Limit:5000S | Memory Limit:65536K | |
Total Submissions:13005 | Accepted:4710 |
Descriptionios
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.spa
You are to help the administrator by reporting the number of bridges in the network after each new link is added.orm
Inputblog
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.ip
Outputget
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.input
Sample Inputstring
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 Outputit
Case 1: 1 0 Case 2: 2 0
大意:給你N個點M條邊的無向連通圖,每次插入一條邊,問插完之後圖中有幾個橋
思路:
不難想到先邊雙連通份量,而後縮點,原圖就變成了有x個點,x-1條邊的樹,其中全部的樹邊都是橋
假若每次只詢問插入邊後圖中橋的個數,不將邊插入,咱們只須要一個樸素LCA便可,x到y之間的全部邊都再也不是橋,時間複雜度爲O(M+N*Q),能夠過
然而每一次要將邊實際插入,這就變得有些複雜了
解法是每次每次找到一個環,用並查集將環中全部的點都指向深度最淺(即最近公共祖先),便可
其實不算特別難,只是很坑,上代碼
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<queue> #define rep(i,a,b) for(int i=a;i<=b;i++) #define dwn(i,a,b) for(int i=a;i>=b;i--) #define MAXN 100050 #define MAXM 410000 using namespace std; int n,m,q,tot=-1; queue<int> Q; int to[MAXM],nxt[MAXM],fir[MAXN],power[30]; int tos[MAXM],nxts[MAXM],firs[MAXN],tots=-1,bj[MAXN]; int num,col[MAXN],cnt,flag,ans,dfn[MAXN],low[MAXN],fa[MAXN],dep[MAXN]; bool bri[MAXM]; void ade(int u,int v){ to[++tot]=v; nxt[tot]=fir[u]; fir[u]=tot; } void ades(int u,int v){ tos[++tots]=v; nxts[tots]=firs[u]; firs[u]=tots; } void init(){ memset(bri,0,sizeof(bri)); memset(fir,-1,sizeof(fir)); memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(bj,0,sizeof(bj)); memset(col,0,sizeof(col)); memset(firs,-1,sizeof(firs)); memset(fa,0,sizeof(fa)); memset(dep,0,sizeof(dep)); tot=-1; tots=-1; num=0; cnt=0; } void Tarjan(int x,int fa){ dfn[x]=low[x]=++num; for(int k=fir[x];k!=-1;k=nxt[k]){ if(to[k]!=fa && !dfn[to[k]]){ Tarjan(to[k],x); if(low[to[k]]>dfn[x]) bri[k]=bri[k^1]=1; low[x]=min(low[x],low[to[k]]); } else if(to[k]!=fa) low[x]=min(low[x],dfn[to[k]]); } } void dfs(int x){ col[x]=cnt; for(int k=fir[x];k!=-1;k=nxt[k]) if(!col[to[k]] && !bri[k]) dfs(to[k]); } void get_tree(int x){ for(int k=firs[x];k!=-1;k=nxts[k]){ if(!fa[tos[k]] && tos[k]!=1){ fa[tos[k]]=x; dep[tos[k]]=dep[x]+1; get_tree(tos[k]); } } } int finds(int x){ if(bj[x]==x) return x; else return bj[x]=finds(bj[x]); } int LCA(int x,int y){ while(!Q.empty()) Q.pop(); while(x!=y){ if(dep[x]<dep[y]) swap(x,y); while(dep[x]>=dep[y] && x!=y) Q.push(x),x=finds(bj[fa[x]]); } if(x==y) return x; } int main(){ power[0]=1; rep(i,1,25) power[i]=power[i-1]*2; while(scanf("%d%d",&n,&m) && n){ init(); rep(i,1,m){ int a,b;scanf("%d%d",&a,&b); ade(a,b);ade(b,a); } Tarjan(1,-1); ++flag; rep(i,1,n) if(!col[i]) ++cnt,dfs(i); ans=cnt; rep(i,1,n){ for(int k=fir[i];k!=-1;k=nxt[k]){ if(col[i]!=col[to[k]]) ades(col[i],col[to[k]]); } } dep[1]=1; fa[1]=0; get_tree(1); rep(i,1,cnt) bj[i]=i; scanf("%d",&q); printf("Case %d:\n",flag); rep(i,1,q){ int a,b,c; scanf("%d%d",&a,&b); if(finds(bj[col[a]])==finds(bj[col[b]])){ printf("%d\n",ans-1); continue; } c=LCA(finds(bj[col[a]]),finds(bj[col[b]])); while(!Q.empty()) bj[Q.front()]=bj[c],Q.pop(),ans--; printf("%d\n",ans-1); } printf("\n"); } }