您的位置:首页 > 其它

PAT-1021解题报告

2013-10-24 11:24 232 查看
惯例,先贴题目:


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
= 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>的数组),稠密矩阵用邻接矩阵比较合适。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  算法 结构