chapter05—Channel Allocation(POJ 1129)

Channel Allocation

Time Limit: 1000MS   Memory Limit: 10000K

Total Submissions: 10300   Accepted: 5245

Description

 

When a radio station is broadcasting over avery large area, repeaters are used to retransmit the signal so that everyreceiver has a strong signal. However, the channels used by each repeater mustbe carefully chosen so that nearby repeaters do not interfere with one another.This condition is satisfied if adjacent repeaters use different channels. 

 

Since the radio frequency spectrum is aprecious resource, the number of channels required by a given network ofrepeaters should be minimised. You have to write a program that reads in adescription of a repeater network and determines the minimum number of channelsrequired.

Input

 

The input consists of a number of maps ofrepeater networks. Each map begins with a line containing the number ofrepeaters. This is between 1 and 26, and the repeaters are referred to byconsecutive upper-case letters of the alphabet starting with A. For example,ten repeaters would have the names A,B,C,...,I and J. A network with zerorepeaters indicates the end of input. 

 

Following the number of repeaters is a listof adjacency relationships. Each line has the form: 

 

A:BCDH 

 

which indicates that the repeaters B, C, Dand H are adjacent to the repeater A. The first line describes those adjacentto repeater A, the second those adjacent to B, and so on for all of therepeaters. If a repeater is not adjacent to any other, its line has theform 

 

A: 

 

The repeaters are listed in alphabeticalorder. 

 

Note that the adjacency is a symmetricrelationship; if A is adjacent to B, then B is necessarily adjacent to A. Also,since the repeaters lie in a plane, the graph formed by connecting adjacentrepeaters does not have any line segments that cross. 

Output

 

For each map (except the final one with norepeaters), print a line containing the minumum number of channels needed sothat no adjacent channels interfere. The sample output shows the format of thisline. Take care that channels is in the singular form when only one channel isrequired.

Sample Input

 

2

A:

B:

4

A:BC

B:ACD

C:ABD

D:BC

4

A:BCD

B:ACD

C:ABD

D:ABC

0

Sample Output

 

1 channel needed.

3 channels needed.

4 channels needed. 

Source

 

Southern African 2001

 

 

題目大意:

   鄰近的轉發器使用不同的頻道,那麼求出在一個範圍內的轉發器所需的數量最少。

編程任務:

讀取轉發器網絡的描述信息,計算出所需的頻道的最小使用量;

分析:

相鄰的轉發器使用不同的頻道,也就是說相鄰的頂點着不同的顏色,那麼可轉化爲點着色的問題,書上說需要的顏色不超過4種,查略了下圖論知識,還是不知道爲什麼,不過不影 響我們解題,我們只要從第一種顏色開始不斷地遍歷,按照需要不斷的增加顏色,直到給每個頂點染色即可。

 

   點着色的一般的做法是從1~n種顏色分別廣度遍歷圖,直到發現k中顏色能滿足要求,則返回;(也就是說需要廣度遍歷圖K次)

核心:(該算法的過程如下所示:先從頂點1開始,依次着色,但是每次着色都必須取可以選擇顏色的最小值)


比如先從頂點A,B,C,D,E,F染色,分別對應顏色的種類,給G染上色1~5,如果發現不能染色成功,說明不能用5種顏色不能完全上色;

Java代碼如下所示:

package ACM;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Scanner;

public class Main {
	private int[][] g ;
	private int[] status ;


	public Main(int n) {
		 g = new int[n][n];
		 status = new int[n];
		resetAllVertex();
	}

	// 因爲是無向的圖
	public void addEdge(char start, char end) {
		int startInt = (int) start - (int) 'A';
		int endInt = (int) end - (int) 'A';
		g[startInt][endInt] = 1;
		// g[endInt][startInt] = 1;
		
	}

	private void resetAllVertex() {
		// TODO Auto-generated method stub
		for (int i = 0; i < status.length; i++) {
			Arrays.fill(g[i], 0);
		}

		Arrays.fill(status, 0);
	}

	// 廣度遍歷
	public boolean BFSTraverse(int colorCount) {
		// 先任意選擇一個節點出發,然後一次廣度遍歷可能需要多次廣度遍歷,可能會存在兩個鼓勵的圖呢?
		// 考慮要全面哈;
		Arrays.fill(status, 0);

		int start;
		while ((start = hasIndexNotZero()) != -1) {
			if (!BFS(start, colorCount)) {
				return false;
			}
		}
		return true;
	}

	private boolean BFS(int start, int colorCount) {
		// TODO Auto-generated method stub
		LinkedList<Integer> llist = new LinkedList<Integer>();
		llist.add(start);
		status[start] = 1;
		boolean flagSucess;
		int vert;
		while (llist.size() > 0) {
			vert = llist.remove();
			flagSucess = true;
			int i;
			int currentColor;
			// 顏色選擇,也就是說先從最小值的顏色選擇,如果不能成功,那麼選擇顏色更大的值;
			for (currentColor = 1; currentColor <= colorCount; currentColor++) {
				for (i = 0; i < status.length; i++) {
					if (g[vert][i] == 1 && status[i] == 0) {
						// 判斷i節點染色爲currentColor的時候,是否能成功,不能成功那麼需要break;
						// 成功的話那麼添加到隊列中;
						boolean flag = true;
						for (int j = 0; j < status.length; j++) {
							if (g[i][j] == 1) {
								if (status[j] == currentColor) {
									flag = false;
									flagSucess = false;
									break;
								}
							}
						}

						if (!flag) {
							break;
						} else {
							status[i] = currentColor;
							flagSucess = true;
							llist.add(i);
							currentColor = 0;
						}
					}
				}

				// 說明染色成功了
				if (flagSucess && i == status.length) {
					break;
				}

			}

			if (!flagSucess) {
				return false;
			}
		}

		return true;
	}

	// 從數組status中找出下標不爲0的值,並返回該下標,也就是節點哈;
	private int hasIndexNotZero() {
		// TODO Auto-generated method stub
		for (int i = 0; i < status.length; i++) {
			if (status[i] == 0) {
				return i;
			}
		}
		return -1;
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int n;
		String str = null;
		Main graph = null;
		char tempStart;
		char tempEnd;

		Scanner cin = new Scanner(new BufferedInputStream(System.in));

		try {
			n = cin.nextInt();
			while (n != 0) {
				graph = null;// 沒啥子意義,爲了通知gc銷燬
				graph = new Main(n);
				for (int i = 0; i < n; i++) {
					str = cin.next().trim();
					if (str.length() > 2) {
						for (int j = 2; j < str.length(); j++) {
							graph.addEdge(str.charAt(0), str.charAt(j));
						}
					}
				}

				int needColor;
				// 開始着色(從第一種顏色開始嘗試)
				for (needColor = 1; needColor <= n; needColor++) {
					if (graph.BFSTraverse(needColor)) {
						break;
					}
				}

				if (needColor == 1) {
					System.out.println("1 channel needed.");
				} else {
					System.out.println(needColor + " channels needed.");
				}
				
				n = cin.nextInt();
			}

		} catch (NumberFormatException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

真是萬事開頭難,本來很簡單的程序,在POJ1129上提交,總是提示Rumming Error,調試了半天,依然沒有解決,後來發現原來是不能加包名。。囧。。不過還好,也算解決了。。







發佈了70 篇原創文章 · 獲贊 2 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章