zoukankan      html  css  js  c++  java
  • poj 3177 Redundant Paths(tarjan边双连通)

    题目链接:http://poj.org/problem?id=3177

    题意:求最少加几条边使得没对点都有至少两条路互通。

    题解:边双连通顾名思义,可以先求一下连通块显然连通块里的点都是双连通的,然后就是各个连通块之间的问题。

    也就是说只要求一下桥,然后某个连通块桥的个数位1的总数,结果就是(ans+1)/2。为什么是这个结果自行画图

    理解一下,挺好理解的。

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    using namespace std;
    const int N = 1e5 + 10;
    const int M = 2e5 + 10;
    struct TnT {
        int v , next;
        bool cut;
    }edge[M];
    int head[N] , e;
    int Low[N] , DFN[N] , Stack[N] , Belong[N];
    bool Instack[N];
    int Index , top , bridge , block;
    void init() {
        memset(head , -1 , sizeof(head));
        e = 0;
    }
    void add(int u , int v) {
        edge[e].v = v , edge[e].next = head[u] , edge[e].cut = false , head[u] = e++;
    }
    void Tarjan(int u , int pre) {
        int v;
        Low[u] = DFN[u] = ++Index;
        Stack[top++] = u;
        Instack[u] = true;
        for(int i = head[u] ; i != -1 ; i = edge[i].next) {
            v = edge[i].v;
            if(v == pre) continue;
            if(!DFN[v]) {
                Tarjan(v , u);
                Low[u] = min(Low[u] , Low[v]);
                if(Low[v] > DFN[u]) {
                    bridge++;
                    edge[i].cut = true;
                    edge[i^1].cut = true;
                }
            }
            else if(Instack[v]) Low[u] = min(Low[u] , DFN[v]);
        }
        if(Low[u] == DFN[u]) {
            block++;
            do {
                v = Stack[--top];
                Instack[v] = false;
                Belong[v] =  block;
            } while(v != u);
        }
    }
    int du[N];
    int main() {
        int f , r;
        while(~scanf("%d%d" , &f , &r)) {
            init();
            for(int i = 0 ; i < r ; i++) {
                int u , v;
                scanf("%d%d" , &u , &v);
                add(u , v);
                add(v , u);
            }
            memset(DFN , 0 , sizeof(DFN));
            memset(Instack , false , sizeof(Instack));
            memset(du , 0 , sizeof(du));
            Index = 0 , block = 0 , top = 0;
            for(int i = 1 ; i <= f ; i++)
                if(!DFN[i]) Tarjan(i , i);
            for(int i = 1 ; i <= f ; i++) {
                for(int j = head[i] ; j != -1 ; j = edge[j].next) {
                    if(edge[j].cut) {
                        du[Belong[i]]++;
                    }
                }
            }
            int ans = 0;
            for(int i = 1 ; i <= block ; i++) {
                if(du[i] == 1) {
                    ans++;
                }
            }
            printf("%d
    " , (ans + 1) / 2);
        }
        return 0;
    }
    
  • 相关阅读:
    我爱网络流之最大流Dinic
    2019ICPC陕西邀请赛复盘
    ZOJ
    ACM省赛及蓝桥总结,且随疾风前行,身后亦须留心
    ZOJ 4124 拓扑排序+思维dfs
    蓝桥 log大侠
    蓝桥历年试题 DNA对比
    “美登杯”上海市高校大学生程序设计邀请赛 (华东理工大学)
    蓝桥历年试题 套娃
    WPF学习之路(七)应用程序和窗口(续)
  • 原文地址:https://www.cnblogs.com/TnT2333333/p/6881882.html
Copyright © 2011-2022 走看看