PAT-1021解题报告

惯例,先贴题目:

1021. Deepest Root (25)

时间限制
1500 ms
内存限制
32000 kB
代码长度限制
16000 B
判题程序
Standard
作者
CHEN, Yue

A graph which is connected and acyclic can be considered a tree. The height 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 (<=10000) 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

读完题目感觉难度不是非常大,总体上需要解决两个问题:

1、如何从图的某一点开始,求的最大深度;

2、如何识别连通子图。


对于第一个问题,我采用DFS的方式,依次遍历以每个结点为根的最大深度(用BFS更直观,这是码完了才意识到的= =)。对于第二个问题,通过一次DFS过程可以标记访问过的结点,如果仍有未访问的结点,那么连通子图的数量就加一。因此,整个算法就有两次DFS的过程,显然效率不够高,但最后居然让我AC了。最后一个case的时间是1300多ms,惊险啊。。下面贴代码:

#include <stdio.h>
#include <stdlib.h>
#include <vector>
#define MAXN 10000
using namespace :: std;

int dfs(vector<int> g[MAXN], int * visited, int N, int start);
int notallvisited(int * visited, int N);
int main(){
	int *hights, *visited, N, i, j, k, m, l;
	scanf("%d", &N);
	vector<int> graph[MAXN + 1];
	hights = (int *)malloc(sizeof(int) * (N + 1));
	visited = (int *)malloc(sizeof(int) * (N + 1));
	for(i = 0; i < N - 1; i++){
		scanf("%d %d", &j, &k);
		graph[j].push_back(k);
		graph[k].push_back(j);
		visited[i] = 0;
	}
	visited[N - 1] = 0;
	visited[N] = 0;
	k = 0;
	while(j = notallvisited(visited, N)){
		k++;
		dfs(graph, visited, N, j);
	}
	if(k > 1){
		printf("Error: %d components", k);
	}
	else{
		for(j = 1; j <= N; j++){
			for(i = 1; i <= N; i++)visited[i] = 0;
			hights[j] = dfs(graph, visited, N, j);
		}
		j = -1;
		k = -1;
		l = -1;
		for(i = 1; i <= N; i++){
			k = -1;
			for(j = 1; j <= N; j++){
				if(hights[j] > k){
					m = j;
					k = hights[j];
				}
			}
			if(i == 1)
				printf("%d\n", m);
			else if(k == l)
				printf("%d\n", m);
			else
				break;
			l = hights[m];
			hights[m] = -1;
		}
	}
	return 0;
}

int dfs(vector<int> g[MAXN + 1], int * visited, int N, int start){
	int max = 0, i, hight;
	visited[start] = 1;
	for(i = 0; i < g[start].size(); i++){
		if(visited[g[start][i]])continue;
		if((hight = dfs(g, visited, N, g[start][i])) > max)max = hight;
	}
	return max + 1;
}

int notallvisited(int * visited, int N){
	int i = 1;
	for(i = 1; i <= N && visited[i]; i++);
	if(i > N)return 0;
	return i;
}

还有一点要说的是,关于图的存储结构。最开始我用的邻接矩阵,定义了int graph[MAXN][MAXN](这里MAXN是10000),然后提交的时候所有的case都是段错误。不知道是不是堆栈溢出的原因,因为一个10000X10000的int二维数组,粗略一算占的内存要有400M,必然吃不消。后来改成了邻接表,问题就解决了。

稀疏矩阵尽量用邻接表存(建立一个vector<int>的数组),稠密矩阵用邻接矩阵比较合适。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值