zoukankan      html  css  js  c++  java
  • poj3352 Road Construction & poj3177 Redundant Paths (边双连通分量)题解

    题意:有n个点,m条路,问你最少加几条边,让整个图变成边双连通分量。

    思路:缩点后变成一颗树,最少加边 = (度为1的点 + 1)/ 2。3177有重边,如果出现重边,用并查集合并两个端点所在的缩点后的点。

    代码:

    /*3352*/
    #include<set>
    #include<map>
    #include<stack>
    #include<cmath>
    #include<queue>
    #include<vector>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    typedef long long ll;
    const int maxn = 5000 + 10;
    const int seed = 131;
    const ll MOD = 1e9 + 7;
    const int INF = 0x3f3f3f3f;
    using namespace std;
    struct Edge{
        int u, v, next;
    }edge[maxn << 1];
    int index, scc_cnt, tot;    //scc_cnt记录SCC
    int dfn[maxn], low[maxn], sccno[maxn], in[maxn], head[maxn];
    stack<int> s;
    void addEdge(int u, int v){
        edge[tot].v = v;
        edge[tot].u = u;
        edge[tot].next = head[u];
        head[u] = tot++;
    }
    void tarjan(int u, int pre){
        dfn[u] = low[u] = ++index;
        s.push(u);
        for(int i = head[u]; i != -1; i = edge[i].next){
            int v = edge[i].v;
            if(!dfn[v]){
                tarjan(v, u);
                low[u] = min(low[u], low[v]);
            }
            else if(v != pre){
                low[u] = min(low[u], dfn[v]);
            }
        }
        if(dfn[u] == low[u]){
            scc_cnt++;
            int a;
            while(1){
                a=s.top();
                s.pop();
                sccno[a] = scc_cnt;
                if(a == u) break;
            }
        }
    }
    
    int main(){
        int n, m;
        scanf("%d%d", &n, &m);
        index = scc_cnt = tot = 0;
        while(!s.empty()) s.pop();
        memset(head, -1, sizeof(head));
        memset(dfn, 0, sizeof(dfn));
        memset(sccno, 0, sizeof(sccno));
        for(int i = 0; i < m; i++){
            int u, v;
            scanf("%d%d", &u, &v);
            addEdge(u, v);
            addEdge(v, u);
        }
        for(int i = 1; i <= n; i++){
            if(!dfn[i])
                tarjan(i, 0);
        }
        memset(in, 0, sizeof(in));
        for(int i = 0; i < tot; i += 2){
            int u = edge[i].u, v = edge[i].v;
            if(sccno[u] != sccno[v]){
                in[sccno[u]]++;
                in[sccno[v]]++;
            }
        }
        int cnt = 0;
        for(int i = 1; i <= scc_cnt; i++){
            if(in[i] == 1) cnt++;
        }
        printf("%d
    ", (cnt + 1) / 2);
        return 0;
    }
    /*3177*/
    #include<set>
    #include<map>
    #include<stack>
    #include<cmath>
    #include<queue>
    #include<vector>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    typedef long long ll;
    const int maxn = 5000 + 10;
    const int seed = 131;
    const ll MOD = 1e9 + 7;
    const int INF = 0x3f3f3f3f;
    using namespace std;
    struct Edge{
        int u, v, next;
    }edge[maxn << 1];
    int index, scc_cnt, tot;    //scc_cnt记录SCC
    int dfn[maxn], low[maxn], sccno[maxn], in[maxn], head[maxn];
    stack<int> s;
    map<int, int> mp[maxn];
    int Find(int x){
        return sccno[x] == x? x : sccno[x] = Find(sccno[x]);
    }
    void addEdge(int u, int v){
        edge[tot].v = v;
        edge[tot].u = u;
        edge[tot].next = head[u];
        head[u] = tot++;
    }
    void tarjan(int u, int pre){
        dfn[u] = low[u] = ++index;
        s.push(u);
        for(int i = head[u]; i != -1; i = edge[i].next){
            int v = edge[i].v;
            if(!dfn[v]){
                tarjan(v, u);
                low[u] = min(low[u], low[v]);
            }
            else if(v != pre){
                low[u] = min(low[u], dfn[v]);
            }
        }
        if(dfn[u] == low[u]){
            scc_cnt++;
            int a;
            while(1){
                a=s.top();
                s.pop();
                sccno[a] = u;
                if(a == u) break;
            }
        }
    }
    
    int main(){
        int n, m;
        scanf("%d%d", &n, &m);
        index = scc_cnt = tot = 0;
        while(!s.empty()) s.pop();
        memset(head, -1, sizeof(head));
        memset(dfn, 0, sizeof(dfn));
        memset(sccno, 0, sizeof(sccno));
        for(int i = 0; i < m; i++){
            int u, v;
            scanf("%d%d", &u, &v);
            addEdge(u, v);
            addEdge(v, u);
        }
        for(int i = 1; i <= n; i++){
            if(!dfn[i])
                tarjan(i, 0);
        }
        for(int i = 1; i <= n; i++) mp[i].clear();
        memset(in, 0, sizeof(in));
        for(int i = 0; i < tot; i += 2){
            int u = edge[i].u, v = edge[i].v;
            if(u > v) swap(u, v);
            mp[u][v]++;
            if(mp[u][v] == 2){
                int fx = Find(u), fy = Find(v);
                if(fx != fy){
                    sccno[fx] = fy;
                }
            }
        }
        for(int i = 0; i < tot; i += 2){
            int u = edge[i].u, v = edge[i].v;
            int fx = Find(u), fy = Find(v);
            if(fx != fy){
                in[fx]++;
                in[fy]++;
            }
        }
        int cnt = 0;
        for(int i = 1; i <= n; i++){
            if(sccno[i] == i && in[i] == 1) cnt++;
        }
        printf("%d
    ", (cnt + 1) / 2);
        return 0;
    }
  • 相关阅读:
    2014编程之美资格赛 第二题 大神和三个小伙伴
    操作系统PV操作——进程同步问题(C#实现)
    [转_管理]成功者必备的15种能力
    [技术相关]List、Dictionary转Dictionary的性能分析
    [项目管理]怎样评定软件开发成果的质量
    Visual Studio 2013 RTM 中文语言包官方下载地址发布
    IIS7报错:如果要使用托管的处理程序,请安装 ASP.NET
    HTTP请求方式中get和post的区别
    asp.net之动态页面和静态页面的区别
    HTML语言语法大全
  • 原文地址:https://www.cnblogs.com/KirinSB/p/9781332.html
Copyright © 2011-2022 走看看