Network(POJ3694+边双连通分量+LCA)
题目链接:http://poj.org/problem?id=3694
题目:
题意:给你一个n个点m条边的无向连通图,进行q次操作,每次操作在u和v之间加一条边,问每次操作之后“桥”的数量。
思路:先tarjan预处理出初始状态“桥”的数量cnt,并进行标记,对于每次操作,进行lca查询,将u和v之间的桥的数量num统计好,并消除标记,结果就是cnt-num。
代码实现如下:
1 #include <set> 2 #include <map> 3 #include <queue> 4 #include <stack> 5 #include <cmath> 6 #include <bitset> 7 #include <cstdio> 8 #include <string> 9 #include <vector> 10 #include <cstdlib> 11 #include <cstring> 12 #include <iostream> 13 #include <algorithm> 14 using namespace std; 15 16 typedef long long ll; 17 typedef pair<ll, ll> pll; 18 typedef pair<ll, int> pli; 19 typedef pair<int, ll> pil;; 20 typedef pair<int, int> pii; 21 typedef unsigned long long ull; 22 23 #define lson i<<1 24 #define rson i<<1|1 25 #define bug printf("*********\n"); 26 #define FIN freopen("D://code//in.txt", "r", stdin); 27 #define debug(x) cout<<"["<<x<<"]" <<endl; 28 #define IO ios::sync_with_stdio(false),cin.tie(0); 29 30 const double eps = 1e-8; 31 const int mod = 10007; 32 const int maxn = 1e5 + 7; 33 const double pi = acos(-1); 34 const int inf = 0x3f3f3f3f; 35 const ll INF = 0x3f3f3f3f3f3f3f; 36 37 int n, m, q, u, v, tot, cnt, num; 38 int head[maxn], dfn[maxn], low[maxn], vis[maxn], pre[maxn], c[maxn]; 39 40 struct edge { 41 int v, next; 42 }ed[maxn<<2]; 43 44 void init() { 45 tot = cnt = num = 0; 46 memset(c, 0, sizeof(c)); 47 memset(vis, 0, sizeof(vis)); 48 memset(dfn, 0, sizeof(dfn)); 49 memset(low, 0, sizeof(low)); 50 memset(head, -1, sizeof(head)); 51 for(int i = 1; i < maxn; i++) { 52 pre[i] = i; 53 } 54 } 55 56 void addedge(int u, int v) { 57 ed[tot].v = v; 58 ed[tot].next = head[u]; 59 head[u] = tot++; 60 ed[tot].v = u; 61 ed[tot].next = head[v]; 62 head[v] = tot++; 63 } 64 65 void tarjan(int x, int fa) { 66 dfn[x] = low[x] = ++num; 67 c[x] = 1; 68 for(int i = head[x]; ~i; i = ed[i].next) { 69 int v = ed[i].v; 70 if(!c[v]) { 71 tarjan(v, x); 72 pre[v] = x; 73 low[x] = min(low[x], low[v]); 74 if(low[v] > dfn[x]) { 75 vis[v] = 1; 76 cnt++; 77 } 78 } else if(c[v] == 1 && v != fa) { 79 low[x] = min(low[x], dfn[v]); 80 } 81 } 82 c[x] = 2; 83 } 84 85 int cut(int x, int y) { 86 int cnt = 0; 87 while(dfn[x] > dfn[y]) { 88 if(vis[x]) { 89 cnt++; 90 vis[x] = 0; 91 } 92 x = pre[x]; 93 } 94 while(dfn[y] > dfn[x]) { 95 if(vis[y]) { 96 cnt++; 97 vis[y] = 0; 98 } 99 y = pre[y]; 100 } 101 while(x != y) { 102 if(vis[x]) { 103 cnt++; 104 vis[x] = 0; 105 } 106 if(vis[y]) { 107 cnt++; 108 vis[y] = 0; 109 } 110 x = pre[x]; 111 y = pre[y]; 112 } 113 return cnt; 114 } 115 116 int main() { 117 //FIN; 118 int icase = 0; 119 while(~scanf("%d%d", &n, &m)) { 120 if(n == 0 && m == 0) break; 121 init(); 122 for(int i = 1; i <= m; i++) { 123 scanf("%d%d", &u, &v); 124 addedge(u, v); 125 } 126 printf("Case %d:\n", ++icase); 127 tarjan(1, 0); 128 scanf("%d", &q); 129 while(q--) { 130 scanf("%d%d", &u, &v); 131 cnt -= cut(u, v); 132 printf("%d\n", cnt); 133 } 134 printf("\n"); 135 } 136 return 0; 137 }
版权声明:本文允许转载,转载时请注明原博客链接,谢谢~