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 }

 

posted @ 2018-07-31 10:58  Dillonh  阅读(276)  评论(0编辑  收藏  举报