历届试题 发现环 并查集+DFS JAVA

6 篇文章 0 订阅
4 篇文章 0 订阅

问题描述

  小明的实验室有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

 

JAVA顶点数为十万的邻接表实现不了,只能过30%

先用并查集得出在环上的一个边,确定出start和end直接DFS搜

import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Scanner;
import java.util.Vector;

 
public class Main {
	  static int fa[];
	  static int n;
	  static int maxn = 3000 + 10;
	  static int[][] g = new int[maxn][maxn]; 
	  static int find(int x) {
		  return x == fa[x] ? x : find(fa[x]);
	  }
	  static boolean same(int a , int b) {
		  if(find(a) == find(b)) {
			  return true;
		  }
		  return false;
	  }
	  static void connect(int a , int b) {
		  a = find(a);
		  b = find(b);
		  if(a != b) {
			  fa[a] = b;
		  }
	  }
	  static int st ,ed;
	  static boolean flag;
	  static List<Integer> arr;
	  static int[] vis;
	  static void dfs(int a,int from) {
		  if(a == ed||flag) {
			  flag = true;
			  return ;
		  } 
		  vis[a] = 1;
		  for(int i = 1 ; i <= n ; i ++) {
			  if(g[a][i] == 1 && vis[i] == 0) {
				  dfs(i,a); 
				  if(flag) {
					  arr.add(i);
					  return;
				  }
			  }
		  }
	  }
	  public static void main(String args[]) {
		  fa = new int[maxn];
		  vis = new int[maxn];
		  for(int i = 0 ; i < maxn ; i++) fa[i] = i;
		 Scanner scan = new Scanner(System.in);
		  n = scan.nextInt();
		 
		 for(int i = 0 ; i < n ; i++) {
			 int from = scan.nextInt();
			 int to = scan.nextInt();
			 
			 if(same(from,to) == false) {
				 g[from][to] = g[to][from] = 1;
				 connect(from,to);
			 }else {
				 st = from;
				 ed = to;
			 }
		 } 
		 arr = new ArrayList<Integer>();
		 flag = false;
		 dfs(st,st);
		 if(arr.contains(st) == false) {
			 arr.add(st);
		 }
		 if(arr.contains(ed) == false) {
			 arr.add(ed);
		 }
		 arr.sort(new Comparator<Integer>() {

			@Override
			public int compare(Integer o1, Integer o2) {
				// TODO Auto-generated method stub
				return o1-o2;
			}
			 
		 });;
		 
		 for(int i = 0 ; i < arr.size() ; i++) {
			 if(i == 0)
			 System.out.print(arr.get(i));
			 else 
			 System.out.print(" " + arr.get(i));
		 } 
	  }
}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值