每日刷题日记

本文介绍了一种利用并查集算法解决网络中出现环路问题的方法,通过构建点与点之间的道路,找出环路上的电脑,以便于修复数据传输bug。
摘要由CSDN通过智能技术生成
  • 发现环

  • 题目:

    题目描述

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

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

    为了恢复正常传输。小明需要找到所有在环路上的电脑,你能帮助他吗?

    输入描述

    输入范围:

    第一行包含一个整数 N 。

    以下 N 行每行两个整数 a,b,表示 a 和 b 之间有一条数据链接相连。

    其中, 1≤≤105,1≤,≤1≤N≤105,1≤a,b≤N。

    输入保证合法。

    输出描述

    按从小到大的顺序输出在环路上的电脑的编号,中间由一个空格分隔。

    输入输出样例

    示例
    5
    1 2
    3 1
    2 4
    2 5
    5 3
    

    输出

    1 2 3 5
    

    运行限制

  • 最大运行时间:1s
  • 最大运行内存: 256M

  • 思路:利用并查集构建点与点之间互通的道路,并且当发现有同属于一个f集合下的点对找到两者之间的路径,即为答案

  • #include <iostream>
    #include <vector>
    #include <algorithm>
    const int MaxNumber= 1e5+10;
    using namespace std;
    int f[MaxNumber];                //father 数组
    vector<int> Path[MaxNumber];     //Path路径,可以互相到达的路径
    int h[MaxNumber];
    vector<int> result;
    
    int Find(int x){
    	return f[x]==x ?x:Find(f[x]);  
    }
    bool Merge(int a,int b){
    	int fa=Find(a);
    	int fb=Find(b);
    	if (fa==fb){
    		return false;
    	}
      if (h[fa]<h[fb]){
        f[fa]=fb;
        h[fb]+=h[fa];
      }else{
    		f[fb]=fa;
    		h[fa]+=h[fb];
    	}
    	return true;
    }
    bool solve(int a,int b){
    	if(h[a]==0){
    		return false;
    	}
    	h[a]=0;
    	for(int i=0;i<Path[a].size();i++){
    		int number=Path[a][i];
    		if (number == b){
    			return true;
    		}
    		if (solve(number,b)){
          result.push_back(number);
    			return true;
    		}
    	}
    	return false;
    }
    
    int main(){
    	int N;
    	cin>>N;
      for(int i=0;i<N;i++){
        f[i]=i;
        h[i]=1;
      }
    	int a1,b1;
    	for(int i=0;i<N;i++){
    		int a,b;
    		cin>>a>>b;
    		if(Merge(a,b)){
    			Path[a].push_back(b);
    			Path[b].push_back(a);
    		}else{
    			a1=a;
    			b1=b;
    		}
    	}
    	solve(a1,b1);
    	result.push_back(a1);
    	result.push_back(b1);
    	sort(result.begin(),result.end());
    	for(int i=0;i<result.size();i++){
    		cout<<result[i]<<" ";
    	}
    	return 0;
    }

  • 40
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值