• poj 3694 Network


    Description:

      给定一张n节点m条边的无向图,执行Q次操作,每次加一条无向边,询问当前桥的数量

    思路:先双联通缩点,然后得到一棵树,对(x,y)连边的时候暴力LCA一下 然后将路径上的点用并查集全都压到LCA上,这样的话下次再搜到被压了的点就可以直接跳到LCA上了,向上压点的同时减去边的数量

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    using namespace std;
    const int N = 100050;
    const int M = 200050;
    
    int head[N],now;
    struct edges{
        int  to,next;
    }edge[M<<1];
    void add(int u,int v){ edge[++now] = {v,head[u]}; head[u] = now;}
    
    int n,m,low[N],dfn[N],tot,cnt,fa[N],pre[N],dep[N],dict[N],ans;
    bool bridge[M<<1];
    struct input{
        int x,y;
    }inp[M];
    
    void init(){
        for(int i = 1; i <= n; i++)  fa[i] = i;
        memset(inp,0,sizeof(inp));
        memset(low,0,sizeof(low));
        memset(dfn,0,sizeof(dfn));  cnt = tot = 0;
        memset(pre,0,sizeof(pre));
        memset(bridge,0,sizeof(bridge));
        memset(head,0,sizeof(head));
        memset(edge,0,sizeof(edge));   now = 1;
        memset(dep,0,sizeof(dep));
        memset(dict,0,sizeof(dict));
    }
    
    void tarjan(int x,int in_edge){  //边-双联通分量缩点 
        low[x] = dfn[x] = ++cnt;
        for(int i = head[x]; i; i = edge[i].next){
            int v = edge[i].to;
            if(!dfn[v]){
                tarjan(v,i);
                low[x] = min(low[x],low[v]);
                if(low[v] > dfn[x])
                  bridge[i] = bridge[i ^ 1] = 1;
            }
            else if(i != (in_edge ^ 1))
              low[x] = min(low[x],dfn[v]);
        }
        return ;
    }
    
    void dfs(int x){
        dict[x] = tot;
        for(int i = head[x]; i; i = edge[i].next){
            int v = edge[i].to;
            if(dict[v] || bridge[i]) continue;
            dfs(v);
        }
        return ;
    }
    
    void new_dfs(int x){
        for(int i = head[x]; i; i = edge[i].next){
            int v = edge[i].to;
            if(pre[x] == v) continue;
            dep[v] = dep[x] + 1;
            pre[v] = x;
            new_dfs(v);
        }
    }
    
    int get(int x){
        if(x != fa[x]) return fa[x] = get(fa[x]);
        return x;
    } 
    
    int lca(int u,int v){
        while(u != v){
            if(dep[u] > dep[v])
              u = pre[u];
            else if(dep[u] < dep[v])
              v = pre[v];
            else{
                u = pre[u];
                v = pre[v];
            }
            u = get(u),v = get(v);
        }
        return u;
    }
    
    int main(){
    //    freopen("data.out","r",stdin); 
        int kase = 0, q;
        while(scanf("%d%d",&n,&m)!= EOF && n + m){
            init();
            int x,y;
            for(int i = 1; i <= m ; i++){
                scanf("%d%d",&x,&y);
                inp[i] = {x,y};
                add(x,y);  add(y,x);
            }
            tarjan(1,0);
            for(int i = 1; i <= n; i++)
              if(!dict[i]) tot++, dfs(i);
            memset(head,0,sizeof(head));
            memset(edge,0,sizeof(edge));  now = 0;
            for(int i = 1; i <= m; i++)  //缩点后得到新图 
              if(dict[inp[i].x] != dict[inp[i].y])
                add(dict[inp[i].x],dict[inp[i].y]),add(dict[inp[i].y],dict[inp[i].x]);
            new_dfs(1);//记录每个点的父节点 
            scanf("%d",&q);
            printf("Case %d:
    ",++kase);
            ans = tot - 1;
            while(q--){
                scanf("%d%d",&x,&y);
                x = get(dict[x]), y = get(dict[y]);
                int tmp = lca(x,y);
                while(x != tmp){  //将x的所有没有压到xy的LCA的点全都压到LCA上 
                    ans--;
                    fa[x] = tmp;
                    x = get(pre[x]);
                }
                while(y != tmp){  //同上 
                    ans--;
                    fa[y] = tmp;
                    y = get(pre[y]);
                }
                printf("%d
    ",ans);
            }
            puts("");
        }
        return 0;
    }
  • 相关阅读:
    PLSQL设置中文
    新建oracle实例
    eclipse中导入项目后中文成乱码解决办法
    安装oracle
    配置java环境变量
    学习springMVC实例1——配置和跳转到HelloWorld
    突破变态限制快捷方式提权法
    对象的内存布局
    XMl转Map-map调用公共模板
    对象的创建
  • 原文地址:https://www.cnblogs.com/Rorshach/p/8684657.html
Copyright © 2020-2023  润新知