思想:
1、用邻接表建图。
2、建完图之后,先把图中的环给找出来。
怎么找呢?
(1)先统计每一个节点的度。
(2)统计完了之后,通过使用队列,把度为1 的点给剔除。每剔除一个,所谓剔除其实就是用一个dis[] 数组来做标记,其相应的邻居的度减一,如果该邻居的度为1了,那么把它加到队列里,重复上述过程,直到队列为空。
(3)最后统计一下,剩下的就是环里的元素。
3、再对环里的元素用BFS搞一下,往外扩散。记录距离。
AC 代码如下:
import java.util.ArrayList; import java.util.LinkedList; import java.util.Queue; import java.util.Scanner; /** * @program: Leetcode * @description: * @author: Wangky * @create: 2019-09-15 15:05 **/ public class Solution { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int T = sc.nextInt(); int time = 1; while ((time )<= T){ int n = sc.nextInt(); // n 个顶点 // construct a graph // 邻接表 ArrayList<Integer> adj[] = new ArrayList[n+1]; for (int i=0;i<adj.length;i++){ adj[i] = new ArrayList<>(); } for(int i=0;i<n;i++){ int x = sc.nextInt(); int y = sc.nextInt(); adj[x].add(y); adj[y].add(x); } // compute the degree of each node int[] degree = new int[n+1]; Queue<Integer> q = new LinkedList<>(); for(int i=1;i<=n;i++){ degree[i] = adj[i].size(); if (degree[i] == 1){ // 度为1的点(即只有一条边),入队列 ((LinkedList<Integer>) q).push(i); } } int[] dis = new int[n+1]; // Topological sort while (!q.isEmpty()){ int node = q.peek(); q.poll(); dis[node] = -1; // 代表该node节点不在环里,可以剔除掉,用 -1 做一个标记 // 节点node 的所有邻接点的度减1 for(int i=0;i<adj[node].size();i++){ int v = adj[node].get(i); degree[v]--; if (degree[v] == 1){ q.offer(v); } } } // Add node in the cycle // 复用该 queue // 从环里往外bfs for(int i=1;i<=n;i++){ if (dis[i] == 0){ q.offer(i); } } while (!q.isEmpty()){ int node = q.peek(); q.poll(); for(int i=0;i<adj[node].size();i++){ int v=adj[node].get(i); if (dis[v] == -1){ // 如果该节点在环外 dis[v] = dis[node]+1; q.offer(v); } } } System.out.print("Case #"+time+": "); for(int i=1;i<=n;i++){ System.out.print(dis[i] + " "); } System.out.println(); time++; } } }