程序设计基础28 关于图的遍历(二)

1021 Deepest Root (25 分)

A graph which is connected and acyclic can be considered a tree. The hight of the tree depends on the selected root. Now you are supposed to find the root that results in a highest tree. Such a root is called the deepest root.

Input Specification:

Each input file contains one test case. For each case, the first line contains a positive integer N (≤10​4​​) which is the number of nodes, and hence the nodes are numbered from 1 to N. Then N−1 lines follow, each describes an edge by given the two adjacent nodes' numbers.

Output Specification:

For each test case, print each of the deepest roots in a line. If such a root is not unique, print them in increasing order of their numbers. In case that the given graph is not a tree, print Error: K components where K is the number of connected components in the graph.

Sample Input 1:

5
1 2
1 3
1 4
2 5

Sample Output 1:

3
4
5

Sample Input 2:

5
1 3
1 4
2 5
3 4

Sample Output 2:

Error: 2 components

这道题的解题经历一波三折。

一,过程一:

    先用并查集找出有几个连通块,若有一个连通块进入以下代码,问题出在blot_num==1之后的for循环中,本来的意思是先把全局变量max_depth在进入子函数前赋给一个depth,然后比较出了这个函数之后max_depth是否发生变化,但忽略了一点,若假设的第i个结点为根节点比i-1个结点为根节点小怎么办,这样也会当成是depth==max_depth而被添加到队列中啊。

void dfs_depth(int u, int depth) {
	vis[u] = true;
	if (depth > max_depth) {
		max_depth = depth;
	}
	for (int i = 0; i < map[u].size(); i++) {
		int v = map[u][i];
		if (vis[v] == false) {
			dfs_depth(v, depth + 1);
		}
	}
}

//以下是mian函数的截取
if (blot_num == 1) {
		for (int i = 1; i <= N; i++) {
			depth = max_depth;
			init();
			dfs_depth(i, 1);
			if (depth < max_depth) {
				tempOri.clear();
				tempOri.push_back(i);
			}
			else if (depth == max_depth) {
				tempOri.push_back(i);
			}
		}
		for (int i = 0; i < tempOri.size(); i++) {
			printf("%d", tempOri[i]);
			if (i != tempOri.size() - 1) {
				printf("\n");
			}
		}
	}

二,过程二:

    所以关于max_depth变化后的对队列的操作还是在子函数中进行比较好,这里为了防止同一个根节点多次遍历到它的最深叶子节点出现重复入列的现象,故用了set.但出现了运行时间超过规定时间的问题,故以后处理数据较多的情况慎用set.

void dfs_depth(int u, int depth, int pre) {
	if (depth >= max_depth) {
		if (depth > max_depth) {
			tempOri.clear();
			max_depth = depth;
		}
		tempOri.insert(I);
	}
	for (int i = 0; i < map[u].size(); i++) {
		int v = map[u][i];
		if (v != pre) {
			dfs_depth(v, depth + 1, u);
		}
	}
}



if (blot_num == 1) {
		for (I = 1; I <= N; I++) {
//			depth = max_depth;
			dfs_depth(I, 1, -1);
		}
//		sort(tempOri.begin(), tempOri.end());
		for (set<int>::iterator it = tempOri.begin(); it != tempOri.end(); it++) {
			printf("%d\n", *it);
		}
	}

三,过程三:

    不能使用set,所以这里我用bool vis[max_n]数组判别是否重复入列,但又出现了内存超限,是因为深度过深的缘故。

void dfs_depth(int u, int depth, int pre) {
	if (depth >= max_depth) {
		if (depth > max_depth) {
			ans.clear();
			init();
			max_depth = depth;
		}
		ans.push_back(I);
		flag[I] = true;
	}
	for (int i = 0; i < map[u].size(); i++) {
		int v = map[u][i];
		if (v != pre) {
			dfs_depth(v, depth + 1, u);
		}
	}
}


if (blot_num == 1) {
		for (I = 1; I <= N; I++) {
			//			depth = max_depth;
			dfs_depth(I, 1, -1);
		}
		//		sort(tempOri.begin(), tempOri.end());
		for (int i = 1; i <= N; i++) {
			if (flag[i] == true) {
				printf("%d\n", i);
			}
		}
	}

四,过程四

    为了解决递归的次数过多,参考了网上的做法用了广度优先算法,明白了对每个结点的层数技术不必用结构体,用一个一维数组用下标号代表结点号即可表示相应结点号的深度。

#include<cstdio>
#include<vector>
#include<queue>
using namespace std;
const int max_n = 10010;
int N = 0;
int blot_num = 0;
int max_depth = -1;
int depth[max_n] = { 0 };
int layer[max_n] = { 0 };
int father[max_n] = { 0 };
bool vis[max_n] = { false };
vector<int> Adj[max_n];
queue<int> que;
int findFather(int x) {
	int a = x;
	while (x != father[x]) {
		x = father[x];
	}
	while (a != father[a]) {
		int z = a;
		a = father[a];
		father[z] = x;
	}
	return x;
}
void Union(int x, int y) {
	int faA = findFather(x);
	int faB = findFather(y);
	if (faA != faB) {
		father[faA] = faB;
	}
}
int BFS(int s) {
	int tdepth = 0;
	fill(layer, layer + max_n, 0);
	que.push(s);
	vis[s] = true;
	layer[s] = 1;
	while (!que.empty()) {
		int t = que.front();
		que.pop();
		tdepth = max(tdepth, layer[t]);
		if (tdepth > max_depth) {
			max_depth = tdepth;
		}
		for (int i = 0; i < Adj[t].size(); i++) {
			if (vis[Adj[t][i]] == false) {
				layer[Adj[t][i]] = layer[t] + 1;
				vis[Adj[t][i]] = true;
				que.push(Adj[t][i]);
			}		
		}
	}
	return tdepth;
}
int main() {
	int x = 0, y = 0;
	scanf("%d", &N);
	for (int i = 1; i <= N; i++) {
		father[i] = i;
	}
	for (int i = 0; i < N - 1; i++) {
		scanf("%d %d", &x, &y);
		Adj[x].push_back(y);
		Adj[y].push_back(x);
		Union(x, y);
	}
	for (int i = 1; i <= N; i++) {
		vis[findFather(i)] = true;
	}
	for (int i = 1; i <= N; i++) {
		if (vis[i] == true) {
			blot_num++;
		}
	}
	if (blot_num == 1) {
		for (int i = 1; i <= N; i++) {
			fill(vis, vis + max_n, false);
			depth[i] = BFS(i);
		}
		for (int i = 1; i <= N; i++) {
			if (depth[i] == max_depth) {
				printf("%d\n", i);
			}
		}
	}
	else {
		printf("Error: %d components", blot_num);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq2285580599/article/details/82926523