Caocao's Bridges HDU -tarjan割边模板

  • I - Caocao's Bridges

  •  HDU - 4738
  • 如果在这时  我的结点 u 有一条到 v 的边  而且  low[v] <= dfn[u] 这就表示在 u 结点有一条边  可以返回到之前的结点 并形成一个环  那么显而易见 这根本不会是桥相反  只要对每一个边访问   若  low[v] > dfn [u] 那么这条边即为 桥,对于割点有一个 等号的问题,在判断桥中   如果 low[v]==dfn[u] 那么这意味着始末都是这个 u 结点的一个 环而已  (包括自环) 没什么影响  只要是环  那么必然不是桥,而对于割点   如果 low[v]==dfn[u] 那么v及其所有子结点都必须通过 u 结点来访问 u 的祖先  所以 u 仍然是割点
  • 题意:求桥的问题   只不过 求最短的桥
  • 注意三点:
  • 1.原图可能不联通  直接输出 0
  • 2.有重边
  • 3.权值为0的桥,输出 1
  • 每一条边一个id,然后判断是否往回走就不是用v==pre而是id==E[i].id,这样一来若有重边则肯定存在另外至少一个不同id的边可以进行dfs把pre(指向u的后向边)的low更新掉,导致low[v]不会大于dfn[u],就构不成桥的条件了,解决了重边的问题。
  • #include 
    #include 
    #include 
    #include 
    #include 
    #include 
     
    using namespace std;
    const int inf = 0x3f3f3f3f;
    const int maxn = 1010;
    int n, m, indx, vis_time, union_num, ansn;
    int head[maxn], low[maxn], dfn[maxn], ans[maxn];
     
    struct node {
        int to;
        int next;
        int w;
    };
    node edge[2 * maxn * maxn];
     
    void AddEdge(int u, int v, int w)
    {
        edge[indx].to = v;
        edge[indx].w = w;
        edge[indx].next = head[u];
        head[u] = indx++;
     
        edge[indx].to = u;
        edge[indx].w = w;
        edge[indx].next = head[v];
        head[v] = indx++;
    }
     
    void init()
    {
        vis_time = indx = ansn = 0;
        union_num = 1;
        memset(head, -1, sizeof head);
        memset(dfn, 0, sizeof dfn);
        memset(low, 0, sizeof low);
    }
     
    void tarjan(int u, int father)
    {
        low[u] = dfn[u] = ++vis_time;
        int pre_num = 0;
        for (int id = head[u]; id != -1; id = edge[id].next) {
            int v = edge[id].to;
            if (v == father && pre_num == 0) {
                pre_num++;
                continue;
            }
            if (!dfn[v]) {
                union_num++;
                tarjan(v, u);
                low[u] = min(low[u], low[v]);
                if (low[v] > dfn[u])
                    ans[ansn++] = edge[id].w;
            } else if (dfn[v] < dfn[u])
                low[u] = min(low[u], dfn[v]);
        }
    }
     
    int main()
    {
        int u, v, w;
        while (scanf("%d %d", &n, &m) != EOF) {
            if (n == 0 && m == 0)
                break;
            init();
            for (int i = 0; i < m; i++) {
                scanf("%d %d %d", &u, &v, &w);
                AddEdge(u, v, w);
            }
            tarjan(1, 1);
            if (union_num < n)
                puts("0");
            else {
                int true_ans = inf;
                for (int i = 0; i < ansn; i++)
                    if (true_ans > ans[i])
                        true_ans = ans[i];
                if (true_ans == 0)
                    true_ans++;
                else if (true_ans == inf)
                    true_ans = -1;
                printf("%d\n", true_ans);
            }
        }
        return 0;
    }
    

     

你可能感兴趣的:(图论)