发现环

问题描述
  小明的实验室有N台电脑,编号1~N。原本这N台电脑之间有N-1条数据链接相连,恰好构成一个树形网络。在树形网络上,任意两台电脑之间有唯一的路径相连。

  不过在最近一次维护网络时,管理员误操作使得某两台电脑之间增加了一条数据链接,于是网络中出现了环路。环路上的电脑由于两两之间不再是只有一条路径,使得这些电脑上的数据传输出现了BUG。

  为了恢复正常传输。小明需要找到所有在环路上的电脑,你能帮助他吗?
输入格式
  第一行包含一个整数N。
  以下N行每行两个整数a和b,表示a和b之间有一条数据链接相连。

  对于30%的数据,1 <= N <= 1000
  对于100%的数据, 1 <= N <= 100000, 1 <= a, b <= N

  输入保证合法。
输出格式
  按从小到大的顺序输出在环路上的电脑的编号,中间由一个空格分隔。
样例输入
5
1 2
3 1
2 4
2 5
5 3
样例输出
1 2 3 5

拓扑排序

无向图拓扑排序一遍然后输出度为4的所有结点

#include<iostream>
#include<cstring>

using namespace std;

const int N = 100010, M = 200010;

int h[N], e[M], ne[M], idx;
int n;
int w[N];
int q[M], hh, tt = -1;

void topsort(){
    for(int i = 1; i <= n; i ++)
        if(w[i] == 2) q[++ tt] = i;
        
    while(hh <= tt){
        int t = q[hh ++];
        for(int i = h[t]; ~i; i = ne[i]){
            int j = e[i];
            w[j] -= 2;
            if(w[j] == 2) q[++ tt] = j;
        }
    }
}

void add(int a, int b){
    e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
    w[a] ++;
    w[b] ++;
}

int main(){
    memset(h, -1, sizeof h);
    
    cin >> n;
    
    for(int i = 0; i < n; i ++){
        int a, b;
        cin >> a >> b;
        add(a, b);
        add(b, a);
    }
    
    topsort();
    
    for(int i = 1; i <= n; i ++)
        if(w[i] == 4) cout << i << ' ';
    
    return 0;
}

并查集判断环,dfs得结果

在输入边的时候往并查集里面加边ab,如果两个结点ab已经在一个集合里面,那么说明加了这条边以后出现了环,所以可以设置a为起点,b为终点然后dfs一遍即可,注意要走a到b的较长的一条路,否则就只有ab了

#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>

using namespace std;

const int N = 100010, M = 200010;

int h[N], e[M], ne[M], idx;
int n;
int start, aim;
int p[N];
vector<int> res;
int st[N];

struct{
    int a, b;
}edges[N];

int find(int x){
    if(x != p[x]) p[x] = find(p[x]);
    return p[x];
}

void add(int a, int b){
    e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}

int dfs(int u){
    res.push_back(u);
    st[u] = 1;
    if(u == aim) return 1;
    
    for(int i = h[u]; i != -1; i = ne[i]){
        int j = e[i];
        if(st[j] == 0){
            if(u == start && j == aim) continue;
            if(dfs(j)) return 1;
            res.pop_back();
            st[j] = 0;
        }
    }
    return 0;
}

int main(){
    memset(h, -1, sizeof h);
    
    cin >> n;
    
    for(int i = 1; i <= n; i ++) p[i] = i;
    
    for(int i = 0; i < n; i ++){
        int a, b;
        cin >> a >> b;
        
        add(a, b);
        add(b, a);
        
        int x = find(a), y = find(b);
        if(x == y)
            start = a, aim = b;
        else p[x] = y;
    }

    dfs(start);
    
    sort(res.begin(), res.end());
    
    for(int i = 0; i < res.size(); i ++) cout << res[i] << ' ';
    
    return 0;
}
原文地址:https://www.cnblogs.com/tomori/p/13711144.html