lca 一种简单暴力方法
题意: 给出一个无向图, 然后逐渐加边, 求出加边后割边的数目。
思路: 首先找出这个无向图的割边, 割边肯定都是在搜索树上的。 对于每次给出的两个点,只需要往上一点一点找lca就行,如果往上的过程中有割边,那么把这个割边擦去。但是我不明白的是为什么我lca的过程中遇到的点都缩成一个点后就不对。
AC代码:
View Code
#pragma comment(linker, "/STACK:10240000000,10240000000") #include <cstdio> #include <iostream> #include <cstring> #include <string> #include <stack> using namespace std; const int N = 201000; struct EDGE { int u, v, next; bool can; }edge[N*6]; int n, m, num, head[N], low[N], lp[N], step, f[N], ans; stack<int>s; bool in[N]; void add(int u, int v) { edge[num].u = u; edge[num].v = v; edge[num].next = head[u]; edge[num].can = 0; head[u] = num++; } void init() { num = 0; memset(head, -1, sizeof(head)); int u, v; for(int i=1; i<=m; i++) { scanf("%d%d", &u, &v); add(u, v); add(v, u); } } void tarjan(int u, int pre) { low[u] = lp[u] = step++; s.push(u); int v; bool flag = 0; for(int i=head[u]; i!=-1; i=edge[i].next) { v = edge[i].v; if(v == pre && flag == 0) { flag = 1; continue; } if(!lp[v]) { tarjan(v, u); f[v] = i; if(low[v] > lp[u]) { ans++; edge[i].can = 1; edge[i^1].can = 1; } low[u] = min(low[u],low[v]); } else low[u] = min(low[u],lp[v]); } if(low[u] == lp[u]) { int haha; while(1) { haha = s.top(); s.pop(); if(haha == u) break; } } } void get(int a, int b) { int u = a, v = b, s; stack<int>ss; // ss.push(u); // ss.push(v); while(u != v) { while(lp[u] > lp[v]) { s = f[u]; if(edge[s].can) { edge[s].can = 0; edge[s^1].can = 0; ans--; } u = edge[s].u; // ss.push(u); } while(lp[v] > lp[u]) { s = f[v]; if(edge[s].can) { edge[s].can = 0; edge[s^1].can = 0; ans--; } v = edge[s].u; // ss.push(v); } } while(!ss.empty()) { v = ss.top(); ss.pop(); f[v] = f[u]; } } void solve() { step = 1; memset(lp, 0, sizeof(lp)); memset(low, 0, sizeof(low)); memset(f, -1, sizeof(f)); while(!s.empty()) s.pop(); ans = 0; tarjan(1,-1); int q, u, v; scanf("%d", &q); while(q--) { scanf("%d%d", &u, &v); get(u, v); printf("%d\n",ans); } printf("\n"); } int main() { int t=0; while(scanf("%d%d", &n, &m) != EOF) { if(n == 0 && m == 0) break; t++; init(); printf("Case %d:\n",t); solve(); } return 0; }


浙公网安备 33010602011771号