这题是给了一个连通图。
问再加入边的过程中,桥的个数。
先对原图进行双连通分支缩点。可以形成一颗树。
这颗树的边都是桥。
然后加入边以后,查询LCA,LCA上的桥都减掉。
标记边为桥不方便,直接标记桥的终点就可以了。
具体看代码吧!
很好的题目
#include <stdio.h> #include <iostream> #include <algorithm> #include <string.h> #include <queue> #include <vector> using namespace std; const int MAXN = 100010; const int MAXM = 400010; struct Edge { int to,next; bool cut; }edge[MAXM]; int head[MAXN],tot; int Low[MAXN],DFN[MAXN],Stack[MAXN],Belong[MAXN];//Belong数组的值是1~block int Index,top; int block; bool Instack[MAXN]; int bridge; void addedge(int u,int v) { edge[tot].to = v;edge[tot].next = head[u];edge[tot].cut = false; head[u] = tot++; } void Tarjan(int u,int pre) { int v; Low[u] = DFN[u] = ++Index; Stack[top++] = u; Instack[u] = true; for(int i = head[u];i != -1;i = edge[i].next) { v = edge[i].to; if( v == pre )continue; if( !DFN[v] ) { Tarjan(v,u); if(Low[u] > Low[v])Low[u] = Low[v]; if(Low[v] > Low[u]) { bridge++; edge[i].cut = true; edge[i^1].cut = true; } } else if(Instack[v] && Low[u] > DFN[v]) Low[u] = DFN[v]; } if(Low[u] == DFN[u]) { block++; do { v = Stack[--top]; Instack[v] = false; Belong[v] = block; } while( v != u ); } } void init() { tot = 0; memset(head,-1,sizeof(head)); } vector<int>vec[MAXN]; int father[MAXN]; int dep[MAXN]; int a[MAXN]; void lca_bfs(int root) { memset(dep,-1,sizeof(dep)); dep[root] = 0; a[root] = 0;//桥的标记,标记桥的一个点 father[root] = -1; queue<int>q; q.push(root); while(!q.empty()) { int tmp = q.front(); q.pop(); for(int i = 0;i < vec[tmp].size();i++) { int v = vec[tmp][i]; if(dep[v]!=-1)continue; dep[v] = dep[tmp]+1; a[v] = 1; father[v] = tmp; q.push(v); } } } int ans; void lca(int u,int v) { if(dep[u]>dep[v])swap(u,v); while(dep[u]<dep[v]) { if(a[v]) { ans--; a[v] = 0; } v = father[v]; } while(u != v) { if(a[u]) { ans--; a[u] = 0; } if(a[v]) { ans--; a[v] = 0; } u = father[u]; v = father[v]; } } void solve(int N) { memset(DFN,0,sizeof(DFN)); memset(Instack,false,sizeof(Instack)); Index = top = block = 0; Tarjan(1,1); for(int i = 1;i <= block;i++) vec[i].clear(); for(int u = 1;u <= N;u++) for(int i = head[u];i != -1;i = edge[i].next) if(edge[i].cut) { int v = edge[i].to; vec[Belong[u]].push_back(Belong[v]); vec[Belong[v]].push_back(Belong[u]); } lca_bfs(1); ans = block - 1; int Q; int u,v; scanf("%d",&Q); while(Q--) { scanf("%d%d",&u,&v); lca(Belong[u],Belong[v]); printf("%d ",ans); } printf(" "); } int main() { int n,m; int u,v; int iCase = 0; while(scanf("%d%d",&n,&m)==2) { iCase++; if(n==0 && m == 0)break; init(); while(m--) { scanf("%d%d",&u,&v); addedge(u,v); addedge(v,u); } printf("Case %d: ",iCase); solve(n); } return 0; }