zoukankan      html  css  js  c++  java
  • POJ 3694 Network

    边双连通分量+并查集

    这题算是水过去的吧,4500ms。应该有更好的写法

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<vector>
    #include<algorithm>
    using namespace std;
    
    const int maxn = 100000 + 10; //结点数量
    const int Maxn = 2 * 200000 + 10; //边的数量
    int low[maxn];
    int dfn[maxn];
    int U[Maxn], V[Maxn];//存初始边
    int flag[Maxn];//判断第i条边是不是割边
    struct Edge
    {
        int from, to, id, ans;//ans为1,表示这条边是割边
    } edge[Maxn];
    vector<int>G[maxn];//邻接表
    vector<int>Tree[maxn];//邻接表
    int N, M;//N个结点,M条边
    int tmpdfn;//时间戳
    int tot;
    int Start, End;
    int TxT[maxn];//求边双连通分量用的
    
    int FF[maxn];
    int Cun[maxn];
    int Father[maxn];
    int MA, Num, Q, X;
    
    void init()
    {
        for (int i = 0; i<maxn; i++) G[i].clear();
        for (int i = 0; i<maxn; i++) Tree[i].clear();
        for (int i = 0; i < maxn; i++) Father[i] = i;
        memset(low, 0, sizeof(low));
        memset(dfn, 0, sizeof(dfn));
        memset(flag, 0, sizeof(flag));
        memset(TxT, 0, sizeof(TxT));
        memset(FF, 0, sizeof(FF));
        low[1] = dfn[1] = 1;
        tmpdfn = 0;
        tot = 0;
        Num = 0;
    }
    
    int Find(int x)
    {
        if (x != Father[x]) Father[x] = Find(Father[x]);
        return Father[x];
    }
    
    void AddEdge(int u, int v)
    {
        edge[tot].from = u;
        edge[tot].to = v;
        edge[tot].id = tot;
        edge[tot].ans = 0;
        G[u].push_back(tot);
        tot++;
    
        edge[tot].from = v;
        edge[tot].to = u;
        edge[tot].id = tot;
        edge[tot].ans = 0;
        G[v].push_back(tot);
        tot++;
    }
    
    int Tarjan(int u, int id)
    {
        tmpdfn++;
        int lowu = dfn[u] = tmpdfn;
        for (int i = 0; i<G[u].size(); i++)
        {
            int B = G[u][i];
            if (!dfn[edge[B].to])
            {
                int lowv = Tarjan(edge[B].to, edge[B].id);
                lowu = min(lowu, lowv);
                if (lowv >= dfn[u])
                {
                    if (lowv>dfn[u])
                        edge[B].ans = 1;
                }
            }
            else if (dfn[edge[B].to])
            {
                if (edge[B].id / 2 == id / 2) continue;
                lowu = min(lowu, dfn[edge[B].to]);
            }
        }
        low[u] = lowu;
        return lowu;
    }
    
    void Dfs(int x, int y)
    {
        int XZ = 0;
        for (int i = 0; i<G[x].size(); i++)
        {
            int B = G[x][i];
            if (!flag[edge[B].id / 2])
            {
                XZ = 1;
                flag[edge[B].id / 2] = 1;
                TxT[edge[B].to] = 1;
                int fu = Find(edge[B].from);
                int fv = Find(edge[B].to);
                if (fu != fv) Father[fu] = fv;
                Dfs(edge[B].to, y + 1);
            }
        }
        if (!XZ&&!y) Father[x] = x;
    }
    
    void Slove()
    {
        for (int i = 0; i<2 * M; i++)
            if (edge[i].ans)
            {
                Num++;
                flag[edge[i].id / 2] = 1;
            }
    
        for (int i = Start; i <= End; i++)
        {
            if (!TxT[i])
            {
                TxT[i] = 1;
                Dfs(i, 0);
            }
        }
    }
    
    int FLAGS;
    void DFS(int now, int len, int END)
    {
        FF[now] = 1;
        if (now == END)
        {
            MA = len;
            FLAGS = 1;
            return;
        }
        for (int i = 0; i < Tree[now].size(); i++)
        {
            if (!FF[Tree[now][i]])
            {
                int fu = Find(now);
                int fv = Find(Tree[now][i]);
                if (fu == fv)
                {
                    DFS(Tree[now][i], len, END);
                    if (FLAGS) return;
                }
                else if (fu != fv)
                {
                    Cun[len] = Tree[now][i];
                    DFS(Tree[now][i], len + 1, END);
                    if (FLAGS) return;
    
                }
            }
        }
    }
    
    int main()
    {
        int CASE = 1;
        while (~scanf("%d%d", &N, &M))
        {
            if (!N&&!M) break;
            printf("Case %d:
    ", CASE);
            CASE++;
            init();
            for (int i = 0; i < M; i++)
            {
                scanf("%d%d", &U[i], &V[i]);
                AddEdge(U[i], V[i]);
            }
            Start = 1;
            End = N;
            Tarjan(1, -1);
            Slove();
            for (int i = 0; i < M; i++)
            {
                int fu = Find(U[i]);
                int fv = Find(V[i]);
                if (fu == fv) continue;
                Tree[fu].push_back(fv);
                Tree[fv].push_back(fu);
            }
            scanf("%d", &Q);
            while (Q--)
            {
                MA = 0;
                FLAGS = 0;
                memset(FF, 0, sizeof FF);
                int u, v;
                scanf("%d%d", &u, &v);
                int fu = Find(u);
                int fv = Find(v);
                if (fu == fv)
                {
                    printf("%d
    ", Num);
                    continue;
                }
                DFS(fu ,0, fv);
                Num = Num - MA;
                for (int i = 0; i < MA; i++)
                {
                    int Fa = Find(Cun[i]);
                    Father[Fa] = fu;
                }
                printf("%d
    ", Num);
            }
            printf("
    ");
        }
        return 0;
    }
  • 相关阅读:
    内存泄漏 Memory Leaks 内存优化 MD
    Handler Thread 内部类引起内存泄露分析
    为什么不取消注册BroadcastReceiver会导致内存泄漏
    WebChromeClient 简介 API 案例
    WebViewClient 简介 API 案例
    java.net.URI 简介 文档 API
    android.net.Uri 简介 API
    RV 多样式 MultiType 聊天界面 消息类型 MD
    JS函数声明与定义,作用域,函数声明与表达式的区别
    CSS中table tr:nth-child(even)改变tr背景颜色: IE7,8无效
  • 原文地址:https://www.cnblogs.com/zufezzt/p/4775233.html
Copyright © 2011-2022 走看看