• 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;
    }
  • 相关阅读:
    CentOS6配置清华大学yum源
    Nginx转发导致请求头丢失
    驾驶本到期换新,要想照片拍的好看,办理不耽误时间请按照以下步骤进行
    Postman生成测试报告
    删除Cookie工具Cookie Manager
    datax dataxweb 安装教程
    Qt 窗口标志(Qt WindowFlags)
    Qt QPalette 使用总结
    Qt License分析、开源版与商业版的区别
    notepad++替换 为回退符,如何操作?
  • 原文地址:https://www.cnblogs.com/zufezzt/p/4775233.html
Copyright © 2020-2023  润新知