Codeforces 178B1-B3 Greedy Merchants

题意:给出一张n个点m条边的无向图,然后又q组查询,询问从s节点走到m节点至少要经过多少条桥

思路:先dfs找桥,并给所有边-双连通分量蓝色。根据找到的桥以及桥的两端的节点的颜色,重新建图(每个节点代表一个双连通分量,其实就是形成一棵树),dfs一遍求各个点的深度,然后就是离线的求LCA,距离就是dis[u]+dis[v]-2*dis[LCA(u,v)]

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <stack>
  4 #include <vector>
  5 #include <algorithm>
  6 #define maxn 100010
  7 using namespace std;
  8 
  9 int pre[maxn],bccno[maxn],dfs_clock,bcc_cnt,bg_cnt;
 10 int depth,dep[maxn],ancestor[maxn],f[maxn],vis[maxn],ans[maxn];
 11 pair<int,int> bridge[maxn];
 12 vector<int> G[maxn],g[maxn],qes[maxn],rank[maxn];
 13 stack<int> S;
 14 
 15 int dfs(int u,int fa){
 16     //printf("dfs(%d,%d)
",u,fa);
 17     int lowu = pre[u] = ++dfs_clock;
 18     S.push(u);
 19     for(int i = 0;i < G[u].size();i++){
 20         int v = G[u][i];
 21         if(!pre[v]){
 22             int lowv = dfs(v,u);
 23             lowu = min(lowu,lowv);
 24             if(lowv > pre[u]){
 25                 bridge[bg_cnt++] = make_pair(u,v);
 26             }
 27         }else if(pre[v] < pre[u] && v != fa){
 28             lowu = min(lowu,pre[v]);
 29         }
 30     }
 31     if(lowu == pre[u]){
 32         bcc_cnt++;
 33         while(1){
 34             int x = S.top();S.pop();
 35             bccno[x] = bcc_cnt;
 36             if(x == u)  break;
 37         }
 38     }
 39     return lowu;
 40 }
 41 
 42 void find_bcc(int n){
 43     memset(pre,0,sizeof(pre));
 44     dfs_clock = bg_cnt = bcc_cnt = 0;
 45     dfs(1,-1);
 46 }
 47 
 48 void dfs2(int u,int fa,int d){
 49     //printf("dfs2(%d,%d,%d)
",u,fa,d);
 50     dep[u] = d;
 51     for(int i = 0;i < g[u].size();i++){
 52         int v = g[u][i];
 53         if(v == fa) continue;
 54         dfs2(v,u,d+1);
 55     }
 56 }
 57 
 58 int find(int x){
 59     return x == f[x] ? x : f[x] = find(f[x]);
 60 }
 61 
 62 void LCA(int u,int fa){
 63     //printf("LCA(%d,%d)
",u,fa);
 64     ancestor[u] = u;
 65     for(int i = 0;i < g[u].size();i++){
 66         int v = g[u][i];
 67         if(v == fa) continue;
 68         LCA(v,u);
 69         int fx = find(u),fy = find(v);
 70         if(fx != fy)  f[fx] = fy;
 71         ancestor[find(u)] = u;
 72     }
 73     vis[u] = 1;
 74     for(int i = 0;i < qes[u].size();i++){
 75         int v = qes[u][i];
 76         if(vis[v]){
 77             //printf("both ancestor of (%d,%d) is %d
",u,v,ancestor[find(v)]);
 78             int tmp = dep[u] + dep[v] - 2 * dep[ancestor[find(v)]];
 79             ans[rank[u][i]] = tmp;
 80         }
 81     }
 82 }
 83 
 84 int main(){
 85     int n,m,q;
 86     while(scanf("%d%d",&n,&m) == 2){
 87         while(!S.empty())   S.pop();
 88         for(int i = 1;i <= n;i++)   G[i].clear();
 89         for(int i = 0;i < m;i++){
 90             int a,b;
 91             scanf("%d%d",&a,&b);
 92             G[a].push_back(b);
 93             G[b].push_back(a);
 94         }
 95         find_bcc(n);
 96         //for(int i = 1;i <= n;i++){
 97         //    printf("bccno[%d] = %d
",i,bccno[i]);
 98         //}
 99         //printf("bg:
");
100         //for(int i = 0;i < bg_cnt;i++){
101         //    printf("%d %d bccno: %d %d
",bridge[i].first,bridge[i].second,bccno[bridge[i].first],bccno[bridge[i].second]);
102         //}
103         for(int i = 1;i <= bcc_cnt;i++){
104             g[i].clear();
105             f[i] = i;
106             vis[i] = 0;
107         }
108         for(int i = 0;i < bg_cnt;i++){
109             int a = bridge[i].first;
110             int b = bridge[i].second;
111             g[bccno[a]].push_back(bccno[b]);
112             g[bccno[b]].push_back(bccno[a]);
113         }
114         //for(int i = 1;i <= bcc_cnt;i++){
115         //    printf("g %d:
",i);
116         //    for(int j = 0;j < g[i].size();j++)
117         //        printf("%d ",g[i][j]);
118         //    printf("
");
119         //}
120         depth = 0;
121         dfs2(1,-1,1);
122         //for(int i = 1;i <= bcc_cnt;i++){
123         //    printf("dep[%d] = %d
",i,dep[i]);
124         //}
125         scanf("%d",&q);
126         for(int i = 0;i < q;i++){
127             int a,b,x,y;
128             scanf("%d%d",&x,&y);
129             a = bccno[x];
130             b = bccno[y];
131             qes[a].push_back(b);
132             qes[b].push_back(a);
133             rank[a].push_back(i);
134             rank[b].push_back(i);
135         }
136         LCA(1,-1);
137         for(int i = 0;i < q;i++){
138             printf("%d
",ans[i]);
139         }
140     }
141     return 0;
142 }
View Code
原文地址:https://www.cnblogs.com/zhexipinnong/p/3239789.html