zoukankan      html  css  js  c++  java
  • kuangbin专题 专题九 连通图 POJ 3694 Network

    题目链接:https://vjudge.net/problem/POJ-3694

    题目:给定一个连通图,求桥的个数,每次查询,加入一条边,问加入这条边后还有多少个桥。

    思路:tarjan + 并查集 + lca(朴素)

    先用tarjan缩点(成环缩点),并存下桥,把每个scc都存下一个源点(源点(boss):以这个点代表这个scc)。

    用存下的桥,用并查集重新建图,为了方便之后的操作,并查集建立一颗树,dfn小的在上,dfn大的在下。

    并且标记x和fa[x]之间有桥,在lca过程中,如果fa[x].bridge == 1,说明这个桥仍然存在,然后fa[x].bridge = 0,防止重复计算

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <algorithm>
      4 #include <vector>
      5 using namespace std;
      6 #define pb push_back
      7 
      8 const int N = (int)5e5+10;
      9 int n,m,tot,tim,top,scc,ans;//点,边,链式前向星,时间戳,栈,连通数
     10 int head[N],dfn[N],low[N],scc_no[N],s[N],boss[N];
     11 //链式前向星,dfn,low,联通块编号,栈,父节点,源点
     12 struct node{
     13     int to;
     14     int nxt;
     15 }e[N << 1];
     16 struct _cut{
     17     int x,y;
     18 };
     19 struct xx{
     20     int fa;
     21     int bridge;
     22 }fa[N];
     23 vector<_cut> cut;//
     24 vector<int> poi;//lca
     25 
     26 void init(){
     27     for(int i = 0; i <= n; ++i){
     28         head[i] = -1;
     29         dfn[i] = 0;
     30     }
     31     cut.clear();
     32     scc = tim = tot = 0;
     33 }
     34 
     35 inline void add(int u,int v){
     36     e[tot].to = v;
     37     e[tot].nxt = head[u];
     38     head[u] = tot++;
     39 }
     40 
     41 void tarjan(int now,int pre){
     42     dfn[now] = low[now] = ++tim;
     43     s[top++] = now;
     44 
     45     int to,pre_cnt = 0;
     46     for(int o = head[now]; ~o; o = e[o].nxt){
     47         to = e[o].to;
     48         if(to == pre && pre_cnt == 0) { pre_cnt = 1; continue; }
     49         if(!dfn[to]){
     50             tarjan(to,now);
     51             low[now] = min(low[now],low[to]);
     52             if(dfn[now] < low[to]) cut.pb(_cut{now,to});
     53         }
     54         else if(low[now] > dfn[to]) low[now] = dfn[to];
     55     }
     56 
     57     if(dfn[now] == low[now]){
     58         int p;
     59         ++scc;
     60         boss[scc] = now;//记录该scc的源点
     61         do{
     62             p = s[--top];
     63             scc_no[p] = scc;
     64         }while(now != p);
     65     }
     66 }
     67 //得到源点函数
     68 inline int _boss(int x){
     69     return boss[scc_no[x]];
     70 }
     71 //重建图   boss进行并查集
     72 void rebuild(){
     73     ans = cut.size();
     74     int x,y;
     75     for(int i = 0; i < ans; ++i){
     76         x = _boss(cut[i].x);
     77         y = _boss(cut[i].y);
     78         //dfn上小,下大的树
     79         if(dfn[x] > dfn[y]) swap(x,y);
     80         fa[y].fa = x;
     81         fa[y].bridge = 1;
     82     }
     83 }
     84 
     85 void lca(int x,int y){
     86     int fax = _boss(x);
     87     int fay = _boss(y);
     88     //if(dfn[fax] == dfn[y]) return;
     89 
     90    // poi.pb(fax); poi.pb(fay);
     91     while(dfn[fax] != dfn[fay]){
     92         while(dfn[fax] > dfn[fay]){
     93             if(fa[fax].bridge){
     94                 --ans;
     95                 fa[fax].bridge = 0;
     96             }
     97             fax = fa[fax].fa;
     98         }
     99         while(dfn[fax] < dfn[fay]){
    100             if(fa[fay].bridge){
    101                 --ans;
    102                 fa[fay].bridge = 0;
    103             }
    104             fay = fa[fay].fa;
    105         }
    106     }
    107 
    108 }
    109 
    110 int main(){
    111 
    112     int _case = 0;
    113     while(~scanf("%d%d",&n,&m) && (n+m)){
    114         init();
    115         int u,v;
    116         for(int i = 0; i < m; ++i){
    117             scanf("%d%d",&u,&v);
    118             add(u,v); add(v,u);
    119         }
    120 
    121         tarjan(1,1);
    122         rebuild();
    123 
    124         int q;
    125         scanf("%d",&q);
    126         printf("Case %d:
    ",++_case);
    127         while(q--){
    128             scanf("%d%d",&u,&v);
    129             lca(u,v);
    130             printf("%d
    ",ans);
    131         }
    132     }
    133 
    134 
    135 
    136     return 0;
    137 }
  • 相关阅读:
    🔥低代码音视频开发训练营火热报名中!
    编解码再进化:Ali266 与下一代视频技术
    ICCV 2021口罩人物身份鉴别全球挑战赛冠军方案分享
    提升 RTC 音频体验 从搞懂硬件开始
    只要你有目标,只要你肯努力,成功只是时间问题
    安全感到底来自何方
    工作经验小结
    女人的出路在何方?
    那些以为过去了的
    初出茅庐
  • 原文地址:https://www.cnblogs.com/SSummerZzz/p/12191524.html
Copyright © 2011-2022 走看看