zoukankan      html  css  js  c++  java
  • b_lc_发现环(并查集+dfs / 拓扑排序)

    小明的实验室有N台电脑,编号1~N。原本这N台电脑之间有N-1条数据链接相连,恰好构成一个树形网络。网络中出现了环路。
    从小到大的顺序输出在环路上的电脑的编号(N<=100000)

    方法一:并查集+dfs

    思路
    这题不用并查集找环的起点的话需要 O(n) 时间确定找,会t,这里用了并查集优化找环过程

    #include<bits/stdc++.h>
    using namespace std;
    const int N=1e6+5;
    int n,m,st,ed,found,fa[N],vis[N];
    vector<int> path, g[N];
    int find(int u) {return fa[u]==u ? u : fa[u]=find(fa[u]);}
    void merge(int a, int b) {
        fa[find(a)]=find(b);
    }
    void dfs(int u) {
        if (found) return;
        path.push_back(u);
        if (u==ed) {
            sort(path.begin(), path.end());
            for (int v : path) cout<<v<<' ';
            found=1;
            return;
        }
        for (int v : g[u]) if (!vis[v]) {
            vis[v]=1;
            dfs(v);
            vis[v]=0;
        }
        path.pop_back();
    }
    int main() {
        std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
        cin>>n; for (int i=1; i<=n; i++) fa[i]=i;
        for (int i=0; i<n; i++) {
            int a,b; cin>>a>>b;
            g[a].push_back(b), g[b].push_back(a);
            if (find(a)!=find(b)) merge(a,b);
            else st=a,ed=b;
        }
        dfs(st);
        return 0;
    }
    

    方法二:拓扑排序

    思路
    从入度为 1 的结点开始拓扑排序,遍历到的点入度都减 1,剩下的入度为 2 的结点都是遍历不到的,也就是环上的结点(环上只有一个结点的入度 ≥ 2)

    #include<bits/stdc++.h>
    using namespace std;
    
    const int N=1e5+50;
    int n, s, e, vis[N], fa[N], in[N];
    vector<vector<int>> g;
    
    vector<int> bfs() {
        queue<int> q;
        for (int i=1; i<=n; i++) if (in[i]==1) q.push(i);
        while (!q.empty()) {
            int u=q.front(); q.pop();
            for (int v : g[u]) if (--in[v]==1) {
                q.push(v);
            }
        }
        vector<int> ans;
        for (int i=1; i<=n; i++) if (in[i]==2) ans.emplace_back(i);
        sort(ans.begin(), ans.end());
        return ans;
    }
    int main() {
        std::ios::sync_with_stdio(false);
        cin >> n;
        g.resize(n+1);
    
        for (int i=0; i<n; i++) {
            int a, b; cin >> a >> b;
            g[a].emplace_back(b), g[b].emplace_back(a);
            in[a]++, in[b]++;
        }
        vector<int> ans=bfs();
        for (int i=0; i<ans.size(); i++) cout << ans[i] << ' ';
        return 0;
    }
    

    复杂度分析

    • Time:O(n),
    • Space:O(n),
  • 相关阅读:
    技术列表
    常用软件开发工具
    EXCEL数据导入SQL2008相关操作
    点点滴滴
    揪出ASP.NET 2.0四大“插件”的总后台 ASPNETDB
    古人说
    好点子都是偷来的:史上最感性的60堂创新课读书摘要
    我是怎么割韭菜的:一个骗子的悔过与自白读书摘要
    人生如我读书摘要
    德米安:彷徨少年时读书摘要
  • 原文地址:https://www.cnblogs.com/wdt1/p/13526130.html
Copyright © 2011-2022 走看看