题目大意:
给你一个无向图,然后再给你一个Q代表有Q次询问,每一次加一条边之后还有几座桥。在这里要对重边进行处理。
每次加入一条边之后,在这条搜索树上两个点的公共祖先都上所有点的桥都没了。
这里重边的处理上要说一下, 我以前第一写的时候根本没考虑这个问题,但是居然过了。。。过了。。。 很扯淡,但是重边的问题确实是存在、
这里我们 使用一个 bridge 数组来保存桥, 因为有重边的存在 只有 bridge 数量为 1 的时候这个路径才算是桥,否则则不是桥
bridge[i] 是指 i 和 father[i] 是一座桥
题目大意:
给你一个无向图,然后再给你一个Q代表有Q次询问,每一次加一条边之后还有几座桥。在这里要对重边进行处理。
每次加入一条边之后,在这条搜索树上两个点的公共祖先都上所有点的桥都没了。
这里重边的处理上要说一下, 我以前第一写的时候根本没考虑这个问题,但是居然过了。。。过了。。。 很扯淡,但是重边的问题确实是存在、
这里我们 使用一个 bridge 数组来保存桥, 因为有重边的存在 只有 bridge 数量为 1 的时候这个路径才算是桥,否则则不是桥
bridge[i] 是指 i 和 father[i] 是一座桥
#include <iostream> #include <cstdlib> #include <cstdio> #include <algorithm> #include <vector> #include <queue> #include <cmath> #include <stack> #include <cstring> usingnamespace std; #define INF 0xfffffff #define min(a,b) (a<b?a:b) #define maxn 100005 int m, n, Time, ans; int dfn[maxn], low[maxn], Father[maxn], bridge[maxn]; vector<int> G[maxn]; void init() { memset(dfn, 0, sizeof(dfn)); memset(low, 0, sizeof(low)); memset(bridge, 0, sizeof(bridge)); memset(Father, 0, sizeof(Father)); Time = ans = 0; for(int i=0; i<=n; i++) G[i].clear(); } void Tarjan(int u,int fa) { dfn[u] = low[u] = ++Time; Father[u] = fa; int len = G[u].size(), v; for(int i=0; i<len; i++) { v = G[u][i]; if( !low[v] ) { Tarjan(v, u); low[u] = min(low[u], low[v]); if(dfn[u] < low[v]) { bridge[v] ++; ans ++; } } elseif(v != fa) { low[u] = min(low[u], dfn[v]); if(dfn[u] < low[v]) { bridge[v] ++; ans --; } } } } void Lca(int a,int b) { if(a == b) return ; if(dfn[a] > dfn[b]) { if( bridge[a] == 1) { bridge[a] = 0; ans --; } Lca(Father[a], b); } else { if(bridge[b] == 1) { bridge[b] = 0; ans --; } Lca(a, Father[b]); } } int main() { int cas = 1; while(scanf("%d %d",&n, &m), m+n) { int Q, a, b; init(); while(m --) { scanf("%d %d",&a, &b); G[a].push_back(b); G[b].push_back(a); } scanf("%d", &Q); Tarjan(1, 0); // printf("%d\n", ans); printf("Case %d:\n", cas ++); while(Q --) { scanf("%d %d",&a, &b); Lca(a, b); printf("%d\n", ans); } } return0; } /* 4 4 1 2 2 1 2 3 1 4 2 1 2 3 4 */
时间: 2025-01-05 13:54:59