一道特別考驗語言功底的題目,首先它的輸入與輸出,對於我這種沒有處理過複雜的輸入,以及輸出的渣渣來說,浪費了大量的時間,好在現在還稍微來得及,不怕不怕啦。緊接着,整個題目的要求也是比較複雜的,首先允許存在重複的數字對,也就是說,在輸入的過程中,需要去重。若重複,則忽略。(具體實現過程中,使用一個edges的map表來去重的。)其次,順序不唯一,同樣的輸入,打亂順序後,會導致不同的輸出。比如樣例1與樣例3。
結合題意,且對於樹這種結構,首先需要確定根節點(那個沒有父節點的),其次從根節點開始能夠保證遍歷所有的節點,且僅僅遍歷一次。這就是這道題目解題的思路。而且,看題目中的要求,數字大小爲1~2^31,所以這裏不能夠使用數組了,所以可以使用map來存儲,首先需要一個鄰接表的存儲方式來存儲讀入的數據,其次需要一個字段來判斷節點是否有父節點,爲了便於實現對應不同的輸入順序有不同的輸出過程,需要增加一個時間戳標記位timestamp和深度標記位dist來表示距離根節點的距離。
緊接着就是bfs的過程了,bfs過程必然用到隊列的,所以整個過程代碼實現如下:
import java.util.*;
import java.io.*;
public class Main{
/** 以鄰接表的形式存儲整個樹。 */
static HashMap<Integer,ArrayList<Integer>> hh =new HashMap<>();
/** 存下每個點的時間戳,用於確認bfs遍歷的順序 */
static HashMap<Integer,Integer>timestamp=new HashMap<>();
/** 節點到根節點的距離。 */
static HashMap<Integer,Integer>dist=new HashMap<>();
static HashMap<Integer,Boolean>has_father=new HashMap<>();
static HashMap<Edges,Boolean>edges=new HashMap<>();
public static void main(String[] args) throws IOException {
Scanner sc=new Scanner(System.in);
BufferedReader bf=new BufferedReader(new InputStreamReader(System.in));
int n=sc.nextInt();
while (n!=0){
n--;
String str[]=sc.next().split(",");
int a=Integer.parseInt(str[0]);
int b=Integer.parseInt(str[1]);
/* 存儲時間戳記錄的次序 */
int tm=0;
Edges edge=new Edges(a,b);
if (edges.containsKey(edge)){
continue;//用來除去序列中重複的邊。
}else{
edges.put(edge,true);
}
if (!timestamp.containsKey(a)){
timestamp.put(a,tm++);
}
if (!timestamp.containsKey(b)){
timestamp.put(b,tm++);
}
has_father.put(b,true);
if (!hh.containsKey(a)){
ArrayList<Integer>list=new ArrayList<>();
list.add(b);
hh.put(a,list);
}else{
hh.get(a).add(b);
}
}
String result=process(n);
System.out.println(result);
}
private static String process(int n) {
String result="";
int root=-1;
for (Integer p: hh.keySet()){
if (has_father.get(p)==null){
root=p;
break;
}
}
if (root==-1){
return "Not a tree";
}
else{
ArrayList<Integer>res=bfs(root);
/* 進行寬度優先遍歷 */
if (res.size()<timestamp.size()){
/* 如果整個樹是不連通的,則判定不是一棵樹 */
return "Not a tree";
}else{
result+=res.get(0)+"";
for (int i=1;i<res.size();i++){
result+=","+res.get(i);
}
}
}
return result;
}
private static ArrayList<Integer> bfs(int root) {
Queue<Integer>q=new LinkedList<>();
q.offer(root);
ArrayList<Integer>nodes = new ArrayList<>();
dist.put(root,0);
while(!q.isEmpty()){
int t=q.poll();
nodes.add(t);
ArrayList<Integer>tem=hh.get(t);
if (tem==null){
continue;
}
for (Integer temp: tem){
/* 當前節點已經被遍歷過,說明在序列中該節點存在多個父節點 */
if (dist.containsKey(temp)){
return new ArrayList<>();
}
dist.put(temp,dist.get(t)+1);
q.offer(temp);
}
}
/*雙關鍵字排序*/
ArrayList<ArrayList<Integer>>ans=new ArrayList<>();
for (Integer ver:nodes){
ArrayList<Integer>list=new ArrayList<Integer>();
list.add(dist.get(ver));
list.add(timestamp.get(ver));
list.add(ver);
ans.add(list);
}
nodes.clear();
Collections.sort(ans, new Comparator<ArrayList<Integer>>() {
@Override
public int compare(ArrayList<Integer> o1, ArrayList<Integer> o2) {
if (Objects.equals(o1.get(0), o2.get(0))){
return o1.get(1)-o2.get(1);
}
return o1.get(0)-o2.get(0);
}
});
for (ArrayList<Integer>t:ans){
nodes.add(t.get(2));
}
return nodes;
}
}
class Edges{
int first;
int second;
public Edges(int first,int second){
this.first=first;
this.second=second;
}
}