天天看點

poj 3694 pku 3694 Network tarjan求割邊 lca

題意:給你一個連通圖,然後再給你n個詢問,每個詢問給一個點u,v表示加上u,v之後又多少個橋。一個最容易想到的辦法就是先加邊找橋,加邊找橋,這樣可定逾時。那麼就可以縮點,因為如果一條邊不是橋那麼無論怎麼加邊他肯定都不會變成橋,這樣我吧不是橋的點縮成一個點。這樣全圖就都是橋,這樣的話,我們就在加的遍裡面去找如果加的邊是同一個點,那麼,肯定不會減少橋,但是如果不是同一個,那麼橋肯定減少~。

代碼如下:

poj 3694 pku 3694 Network tarjan求割邊 lca
poj 3694 pku 3694 Network tarjan求割邊 lca
1 #include <stdio.h>
  2 #include <string.h>
  3 #include <iostream>
  4 #include <algorithm>
  5 #include <stdlib.h>
  6 #include <vector>
  7 #include <queue>
  8 #define loop(s,i,n) for(i = s;i < n;i++)
  9 #define cl(a,b) memset(a,b,sizeof(a))
 10 using namespace std;
 11 const int maxn = 100005;
 12 int low[maxn],dfn[maxn],set[maxn],father[maxn],dfsclock,cut;
 13 vector<int >g[maxn];
 14 int find(int x)
 15 {
 16     if(set[x] != x)
 17     set[x] = find(set[x]);
 18 
 19     return set[x];
 20 }
 21 int merge(int x,int y)
 22 {
 23     x = find(x);
 24     y = find(y);
 25     if(y != x)
 26     {
 27         set[y] = x;
 28         return 1;
 29     }
 30     return 0;
 31 }
 32 
 33 void tarjan(int u,int pre)
 34 {
 35     int v,i,j;
 36     dfn[u] = low[u] = ++dfsclock;
 37     loop(0,i,g[u].size())
 38     {
 39         v = g[u][i];
 40         if(!dfn[v])
 41         {
 42             tarjan(v,u);
 43             father[v] = u;
 44             low[u] = min(low[v],low[u]);
 45             if(low[v] > dfn[u])
 46             cut++;
 47             else
 48             merge(u,v);
 49         }
 50         else if(v != pre)
 51         low[u] = min(low[u],dfn[v]);
 52     }
 53 }
 54 void lca(int u,int v)
 55 {
 56 
 57     while(u != v)
 58     {
 59         while(dfn[u] >= dfn[v] && u != v)
 60         {
 61             if(merge(u,father[u]))
 62             cut--;
 63             u = father[u];
 64         }
 65         while(dfn[v] >= dfn[u] && u != v)
 66         {
 67             if(merge(v,father[v]))
 68             cut--;
 69             v =  father[v];
 70         }
 71     }
 72 }
 73 int main()
 74 {
 75     int n,m;
 76     int i,x,y,cas = 0;
 77     while(scanf("%d %d", &n,&m)&&(n||m))
 78     {
 79         int u,v;
 80         printf("Case %d:\n",++cas);
 81         loop(1,i,n+1)
 82         {
 83             g[i].clear();
 84             set[i] = i;
 85             father[i] = 0;
 86         }
 87         while(m--)
 88         {
 89             scanf("%d %d",&u,&v);
 90             g[u].push_back(v);
 91             g[v].push_back(u);
 92 
 93         }
 94         cl(dfn,0);
 95         cl(low,0);
 96         cut = dfsclock = 0;
 97 
 98         int k;
 99         scanf("%d",&k);
100         tarjan(1,-1);
101 
102         while(k--)
103         {
104             scanf("%d %d",&u,&v);
105             lca(u,v);
106             printf("%d\n",cut);
107         }
108         puts("");
109     }
110     return 0;
111 }      

View Code

轉載于:https://www.cnblogs.com/0803yijia/p/3227711.html