POJ 3694 Network

tarjan+LCA。 
先用tarjan进行缩点。 
然后用dfn[u] < low[v]判断是不是桥。 
讲桥标记起来并且计算出桥数。 
对于每个案例的u和v 
利用LCA用fath数组先找到u和v的祖先,如果在路径中出现的桥,就把桥标记成普通边并将桥数–。 
然后输出对应的桥数

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<algorithm>
  4 
  5 using namespace std;
  6 
  7 const int maxn = 100006;
  8 const int maxm = 200005;
  9 int n, m, tol, cnt;
 10 int brinum;
 11 
 12 struct Node {
 13     int u;
 14     int v;
 15     int next;
 16 };
 17 Node node[2 * maxm];
 18 int dfn[maxn];
 19 int low[maxn];
 20 int fath[maxn];
 21 int head[maxn];
 22 bool vis[maxn];
 23 bool bridge[maxn];
 24 
 25 void init() {
 26     brinum = tol = cnt = 0;
 27     memset(dfn, 0, sizeof(dfn));
 28     memset(low, 0, sizeof(low));
 29     memset(node, 0, sizeof(node));
 30     memset(fath, 0, sizeof(fath));
 31     memset(head, -1, sizeof(head));
 32     memset(vis, false, sizeof(vis));
 33     memset(bridge, 0, sizeof(bridge));
 34 }
 35 
 36 void addnode(int u, int v) {
 37     node[tol].u = u;
 38     node[tol].v = v;
 39     node[tol].next = head[u];
 40     head[u] = tol++;
 41 }
 42 
 43 void dfs(int u, int fa) {
 44     dfn[u] = low[u] = ++cnt;
 45     fath[u] = fa;
 46     for(int i=head[u]; i != -1; i=node[i].next) {
 47         int v = node[i].v;
 48         if(!dfn[v]) {
 49             dfs(v, u);
 50             low[u] = min(low[u], low[v]);
 51         } else if(v != fa) {
 52             low[u] = min(low[u], dfn[v]);
 53         }
 54     }
 55 }
 56 
 57 void tarjan() {
 58     dfs(1, 1);
 59 }
 60 
 61 void findbridge() {
 62     for(int v=1; v<=n; v++) {
 63         int u = fath[v];
 64         if(dfn[u] < low[v] && u != v) {
 65             bridge[v] = true;
 66             brinum++;
 67         }
 68     }
 69 }
 70 
 71 void LCA(int u, int v) {
 72     while(dfn[u] > dfn[v]) {
 73         if(bridge[u]) {
 74             brinum--;
 75             bridge[u] = false;
 76         }
 77         u = fath[u];
 78     }
 79     while(dfn[v] > dfn[u]) {
 80         if(bridge[v]) {
 81             brinum--;
 82             bridge[v] = false;
 83         }                                   
 84         v = fath[v];
 85     }
 86     while(u != v) {
 87         if(bridge[u]) {
 88             bridge[u] = false;
 89             brinum--;
 90         }
 91         if(bridge[v]) {
 92             bridge[v] = false;
 93             brinum--;
 94         }
 95         u = fath[u];
 96         v = fath[v];
 97     }
 98     printf("%d\n", brinum);
 99 }
100 
101 int main() {
102     int cas = 1;
103     while(scanf("%d%d",&n, &m), n||m) {
104         init();
105         for(int i=1; i<=m; i++) {
106             int u, v;
107             scanf("%d%d", &u, &v);
108             addnode(u, v);
109             addnode(v, u);
110         }
111         tarjan();
112         findbridge();
113         int q;
114         scanf("%d", &q);
115         printf("Case %d:\n", cas++);
116         for(int i=1; i<=q; i++) {
117             int u, v;
118             scanf("%d%d", &u, &v);
119             LCA(u, v);
120         }
121         puts("");
122     }
123     return 0;
124 }
View Code

猜你喜欢

转载自www.cnblogs.com/H-Riven/p/9148329.html