zoukankan      html  css  js  c++  java
  • hdu4612-Warm up(边的双连通分量)

    题意:有n个点,m条边,有重边。现在可以任意在图上添加一条边,求桥的最少数目。

    题解:思路就是求出双连通分量之后缩点成为一棵树,然后求出树的直径,连接树的直径就能减少最多的桥。

    难点在于:有!重!边!

    像我这样习惯于无脑用模板的人来说。。。。头疼死了。。。。。。

    既然有重边,dfs的时候就不要标记点,以边为标记,然后照常求分量就好了。

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <string>
    #include <vector>
    #include <bitset>
    #include <cstdio>
    #include <queue>
    #include <stack>
    #include <cmath>
    #include <list>
    #include <map>
    #include <set>
    #define pk(x) printf("x=%d
    ", x)
    using namespace std;
    #define PI acos(-1.0)
    #define EPS 1E-6
    #define clr(x,c) memset(x,c,sizeof(x))
    typedef long long ll;
    typedef pair<int, int> PII;
    
    const int N = 200005;
    const int M = 2000005;
    
    struct Edge {
        int from, to, next;
        int cut;
    } edge[M];
    int cnt_edge;
    int head[N];
    void add_edge(int u, int v)
    {
        edge[cnt_edge].from = u;
        edge[cnt_edge].to = v;
        edge[cnt_edge].next = head[u];
        edge[cnt_edge].cut = 0;
        head[u] = cnt_edge++;
    }
    
    int dfn[N]; int idx;
    int low[N];
    int stk[N]; int top;
    int kind[N]; int cnt;
    bool in[N];
    
    void tarjan(int u, int pre)
    {
        low[u] = dfn[u] = ++idx;
        in[u] = true;
        stk[++top] = u;
        for (int i = head[u]; i != -1; i = edge[i].next)
        {
            int v = edge[i].to;
            if (i == pre) continue;
            if (!dfn[v])
            {
                tarjan(v, i^1);
                low[u] = min(low[u], low[v]);
                if (low[v] > dfn[u])
                {
                    edge[i].cut = true;
                    edge[i ^ 1].cut = true;
                }
            }
            else low[u] = min(low[u], dfn[v]);
        }
        if (low[u] == dfn[u])
        {
            cnt++;
            int v;
            do {
                v = stk[top--];
                in[v] = false;
                kind[v] = cnt;
            } while (u != v);
        }
    }
    
    vector<int> G[N];
    int ans, ansv;
    
    void dfs(int u, int fa, int d) {
        if (ans < d) {
            ans = d;
            ansv = u;
        }
        for (unsigned i = 0; i < G[u].size(); ++i) {
            int v = G[u][i];
            if (v == fa) continue;
            dfs(v, u, d+1);
        }
    }
    
    void init()
    {
        for (int i = 0; i < N; ++i) G[i].clear();
        memset(dfn, 0, sizeof dfn);
        memset(head, -1, sizeof head);
        top = idx = cnt = cnt_edge = 0;
    }
    int main()
    {
        int n, m;
        while (~scanf("%d%d", &n, &m)) {
            if (n + m == 0) break;
            init();
            int u, v;
            for (int i = 0; i < m; ++i) {
                scanf("%d%d", &u, &v);
                add_edge(u, v);
                add_edge(v, u);
            }
            tarjan(1, -1);
    
            int ret = 0;
            for (int i = 0; i < cnt_edge; ++i) {
                if (edge[i].cut) {
                    int u = edge[i].from;
                    int v = edge[i].to; if (u < v)
                    ret++;
                    G[ kind[u] ].push_back( kind[v] );
                }
            }
            ans = 0; ansv = 0; dfs(1, -1, 0);
            ans = 0; dfs(ansv, -1, 0);
            printf("%d
    ", ret-ans);
    
        }
        return 0;
    }
    /**
    6 6
    1 2 2 3 3 4 4 5 2 6 6 2
    
    6 8
    1 2 2 3 3 4 4 5 2 6 6 2 1 3 4 7
    
    5 4
    2 1 2 3 2 4 2 5
    
    5 5
    2 1 2 3 2 4 2 5 3 4
    
    5 5
    1 2 2 3 3 4 3 4 4 5
    
    
    0
    1
    2
    0
    0
    */

    ======

    wa:12次,tle:1次,mle:3次,ce:2次

    一颗赛艇。。。

  • 相关阅读:
    DRF内置限流组件之自定义限流机制
    DRF内置权限组件之自定义权限管理类
    DRF内置认证组件之自定义认证系统
    java基础(15)--多态
    java基础(13)--静态变量、静态代码块、实例代码块
    java基础(12)--static变量/方法 与 无 static的变量/方法的区别
    java基础(11)--封装
    java基础(10)--空指针异常
    java基础(9)--方法重载
    java基础(8)--键盘输入
  • 原文地址:https://www.cnblogs.com/wenruo/p/5882958.html
Copyright © 2011-2022 走看看