用局部替換方式求解最小生成樹 java

從T=空集開始

for(圖中每條邊e)

       if 加入e不構成環,則 T=T+e

       else e‘ 是環上權重最大的邊,T = T+e'

 

解:利用鄰接表形式存儲圖,用另一張圖,每一次向新圖裏面加入一條邊,從加入邊的頂點開始做dfs遍歷。如果遇到後向邊,就說明圖中有環,找出最大的邊,刪掉該邊,再加入邊,繼續dfs過程,直到所有邊都加入。

這裏圖用hashmap存儲,

static Map<Integer, LinkedList<Pair<Integer, Integer>>> graph = new HashMap<>();//鄰接表存儲圖 ,pair存到達點和權重

初始化:

@SuppressWarnings({ "unchecked", "rawtypes" })
	public static void ini() {
		System.out.println("請輸入頂點數:");
		v = scanner.nextInt(); 
		visited = new int[v];
		pre = new int[v]; 
		
		System.out.println("請輸入邊數和各條邊以及權重:");
		e = scanner.nextInt();
		
		for(int i=0; i<e; i++) 
		{
			resGraph.put(i, new LinkedList<>()); 
			graph.put(i, new LinkedList<>()); 
		}
		
		for(int i=0; i<e; i++)
		{
			int from = scanner.nextInt();
			int to = scanner.nextInt();
			int weight = scanner.nextInt();
			if(weight<=0) {
				System.out.println("權重必須大於0!\n重新輸入:");
				weight = scanner.nextInt();
			}
			graph.get(from).add(new Pair(to, weight));
			graph.get(to).add(new Pair(from, weight));//雙向添加
			//DFS(from, visited, graph);
		}
		printGrapg(graph);
	}

深度優先搜索:

//dfs遍歷
	public static void DFS(int start, int[] visited ,Map<Integer, LinkedList<Pair<Integer, Integer>>> graph) {
		for(int i=0; i<v; i++) {
			visited[i] = white;//初始化都是白色
			pre[i] = -1;//沒有前驅點 
		}
		dfsVisit(0, visited, graph);//從0開始遍歷
	}
	
	//dfs遞歸部分
	public static void dfsVisit(int start,int[] visited, Map<Integer,LinkedList<Pair<Integer, Integer>>> graph) {
		time++;
		visited[start] = gray;
		for(Pair<Integer, Integer> p:graph.get(start))
		{
			if(visited[p.getKey()]==gray && p.getKey()!=pre[start])//是灰色出現了環,後向邊
			{
				findMax(start, p.getKey(), p.getValue(), graph);//標記
			}
			if(visited[p.getKey()]==white)
			{
				pre[p.getKey()] = start;
				dfsVisit(p.getKey(), visited, graph);
			}			
		}
		visited[start] = black;
		time++;
	}

 

找最大權重的邊:這裏用pre數組記錄了每一個點的前向點,根據此來找到環和最大邊

//找最大權值的邊
	public static void findMax(int end, int start, int weight, Map<Integer,LinkedList<Pair<Integer, Integer>>> graph) { 
		//System.out.println("bugbugbugbugbug:"+end+" "+start+" "+weight);
		int a = pre[end], endP = end;
		int maxKey = 0, w=0, maxEnd=start;
		while(a!=pre[start]) {
			w = findWeight(endP, a); 
			if(maxKey <= w) {
				maxEnd = endP;
				maxKey = w;
			}
			endP = a;
			a = pre[endP];
		}
		if(maxKey>weight) {//最大的是樹邊裏面的
			//isMax.put(maxEnd, pre[maxEnd]);
			delete(graph, maxEnd, pre[maxEnd]);
			delete(graph, pre[maxEnd], maxEnd);
		}else {
			//isMax.put(end, start);//最大邊是該後向邊
			delete(graph, end, start);
			delete(graph, start, end);
		}
		 
	}

主函數:

for(int i=0; i<v;i++)
		{
			for(int j=0; j<graph.get(i).size(); j++)
			{
				
					from = i; to = graph.get(i).get(j).getKey(); w = graph.get(i).get(j).getValue();
					if(from<to)
					{
					resGraph.get(from).add(new Pair<Integer, Integer>(to, w));//每次添加一條邊
					resGraph.get(to).add(new Pair<Integer, Integer>(from, w));
					DFS(to, visited, resGraph);
				}
				
			}
		}
		int count=0;
		for(int i=0; i<v; i++) {
			System.out.print("\n"+i+" :: ");
			for(Pair<Integer, Integer> p : resGraph.get(i))
			{
				System.out.print("  "+i+"->"+p.getKey()+" "+p.getValue());//i->p 3
				count+=p.getValue();
			}
		}
		System.out.println(count/2);

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章