• POJ3694 e-DCC+LCA


    xg,卡时间过的

    题意

      给了一张n个点m个边的无向图,Q个操作,第i次操作插入边x,y。对于每次插入边,输出桥的个数。

    思路  

      tarjan+缩点后,形成一个树,桥的个数即为点的个数cnt-1.

      对树进行倍增预处理。

      每次操作插入x,y点后,log查找到x和y的lca,把x,y到lca路径上的点进行标记,每标记了一个未被标记的点,cnt--。

      

     #include <iostream>
     #include <cmath>
     #include <cstdio>
     #include <cstring>
     #include <string>
     #include <map>
     #include <iomanip>
     #include <algorithm>
     #include <queue>
     #include <stack>
     #include <set>
     #include <vector> 
    
    #define bug cout<<"--------------"<<endl
    #define sp ' '
    using namespace std;
    typedef long long ll;
    
    const int maxn = 1e5+10;
    const int SIZE = 4e5+10;
    int tot = 0;
    int head[SIZE],ver[SIZE],nextt[SIZE];
    void add(int x,int y)
    {
        ver[++tot] = y,nextt[tot] = head[x] , head[x] = tot;
    }
    int n,m,num,t;
    int dfn[maxn],low[maxn],bridge[SIZE];
    void tarjan(int x,int in_edge)
    {
        dfn[x] = low[x] = ++num;
        for(int i = head[x];i;i = nextt[i]){
            int y = ver[i];
            if(!dfn[y]){
                tarjan(y,i);
                low[x] = min(low[x],low[y]);
                if(low[y] > dfn[x])
                    bridge[i] = bridge[i^1] = 1;
                 //que.push(make_pair(min(i,i^1),max(i,i^1)));
            }
            else if(i!=(in_edge^1)) 
                low[x] = min(low[x],dfn[y]);
        }
    }
    int c[maxn],dcc;
    void dfsc(int x)
    {
        c[x] = dcc;
        for(int i = head[x];i;i = nextt[i]){
            int y = ver[i];
            if(c[y] || bridge[i]) continue;
            dfsc(y);
        }
    }
    int tc = 0;
    int hc[SIZE],vc[SIZE],nc[SIZE];
    void addc(int x,int y)
    {
        vc[++tc] = y,nc[tc] = hc[x] , hc[x] = tc;
    }
    int d[maxn],f[maxn][30],fa[maxn];
    void bfs(){
        queue<int> que;
        que.push(1);
        d[1] = 1;
        while(!que.empty()){
            int x = que.front();
            que.pop();
            for(int i = hc[x]; i; i = nc[i]){
                //.......
                
                int y = vc[i];
                
                if(d[y]) continue;
                fa[y] = x;
                //dist[y] = dist[x] + edge[i];
                d[y] = d[x] + 1;
                f[y][0] = x;
                for(int j = 1; j <= t;j++){
                    f[y][j] = f[f[y][j-1]][j-1];
                }
                que.push(y);
            }
        }
    }
    int lca(int x, int y){
        if(d[x] > d[y]) swap(x,y);
        for(int i = t;i >= 0;i--){
            if(d[f[y][i]] >= d[x]) y = f[y][i];
        }
        if(x == y) return x;
        for(int i = t;i >= 0;i--){
            if(f[x][i] != f[y][i]){
                x = f[x][i];
                y = f[y][i];
            }
        }
        return f[x][0];
    } 
    int vis[maxn];
    
    void clearr()
    {
        num = 0;
        memset(head,0,sizeof(head));
        tot = 1;
        memset(low,0,sizeof(low));
        memset(dfn,0,sizeof(dfn));
        memset(bridge,0,sizeof(bridge));
        dcc = 0;
        memset(c,0,sizeof(c));
        memset(d,0,sizeof(d));
        memset(f,0,sizeof(f));
        memset(hc,0,sizeof(hc));
        tc = 0;
        memset(head,0,sizeof(head));
        memset(vis,0,sizeof(vis));
    /*    for(int i=1;i<=n;++i){
            vis[i].clear();
        }
    */
    }
    int main()
    {
       // freopen("input.txt", "r", stdin);
        int casee = 0;
        while(scanf("%d%d",&n,&m)){
            if(n == 0 && m == 0) break;
            clearr();
            for(int i = 1;i <=m ; ++i){
                int x, y;
                scanf("%d%d",&x,&y);
                add(x,y);
                add(y,x);
            }
    
            for(int i = 1; i <= n;++i){
                if(!dfn[i]) tarjan(i,0);
            }
            for(int i = 1;i <= n;++i){
                if(!c[i]){
                    ++dcc;
                    dfsc(i);
                }
            }
            for(int i = 2;i <= tot;i=i+2){
                int x = ver[i],y = ver[i^1];
                if(c[x] == c[y]) continue;        
                addc(c[y],c[x]);
                addc(c[x],c[y]);
            } 
            //bian:tc,point:dcc
            t = log(dcc)/log(2) + 1;
            bfs();
            int ans = dcc - 1;
            //cout<<dcc<<sp<<tc<<endl;
            int Q;
            scanf("%d",&Q);
            printf("Case %d:
    ",++casee );
            while(Q--){
                int x,y;
                scanf("%d%d",&x,&y);
                if(c[x] == c[y]) {
                    printf("%d
    ",ans);
                }
                else {
                    int L = lca(c[x],c[y]);
                    int a = c[x],b = c[y];
                    int pos = a;
    
                    while(pos != L){
                        if(vis[pos] == 0){
                            vis[pos] = 1;
                            ans--;
                        }
                        pos = fa[pos];
                    }
                    pos = b;
                    while(pos != L){
                       // cout<<pos<<endl;
                        if(vis[pos] == 0){
                            vis[pos] = 1;
                            ans--;
                        }
                        pos = fa[pos];
                    }
                    printf("%d
    ",ans );                
                }
    
            } printf("
    ");
    
        }
    }
  • 相关阅读:
    android中使用百度定位sdk实时的计算移动距离
    Android NDK开发常见错误
    cocos2dx中使用iconv转码(win32,iOS,Android)
    史上最全的CSS hack方式一览
    谈谈SQL 语句的优化技术
    PIVOT 和 UPIVOT 的使用(行转列)
    JQuery的Ajax跨域请求的解决方案
    64位windows2003 未在本地计算机上注册 microsoft.jet.oledb.4.0 提供程序
    httpModules 与 httpHandlers
    删除事件查看器中多余的日志分类
  • 原文地址:https://www.cnblogs.com/jrfr/p/13546345.html
Copyright © 2020-2023  润新知