题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4707
解题报告:题目大意是在无向图G中有n个点,分别从0 到n-1编号,然后在这些点之间有n-1条边,可以保证这个图是连通图,并且每条边的长度都是1,然后让你求出从编号为0的点出发,到其它的点的距离大于d的点的个数。
这题的点的个数有500000个,而内存限制为32M,很显然,开邻接矩阵不行,但这题实际上不需要记录边只需要开一位数组就可以了,但是我为了练习一下邻接矩阵的写法,特地用邻接矩阵另外写了一个代码。第一次写邻接矩阵,一开始忘了标记已经走过的点,造成dfs的时候陷入了死循环,一运行就挂了,很明显爆栈了,找了好久,才发现原来走过的点如果不标记还会再走一遍。还有一个很重要的点就是,每组数据结束之后,不要忘记清理内存,不然还是会MLE。然后这题如果不用邻接表写的话,直接定义一个一位数组也行,因为题目虽然没有说,但是实际上题目输入的数据是有顺序的,就是按照从0点开始往其它的点走的顺序来输入的,很显然,这样就方便多了。
邻接表AC代码:
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 using namespace std; 5 const int maxn = 100005; 6 7 struct Node 8 { 9 int d; 10 Node *next; 11 }; 12 13 typedef struct node 14 { 15 int num; 16 Node * next; 17 node() 18 { 19 num = 0; 20 next = NULL; 21 } 22 }LinkList; 23 24 int length[maxn],visit[maxn]; 25 26 void push(LinkList *Link,int s,int e) 27 { 28 int k = Link[s].num - 1; 29 Node *p = Link[s].next; 30 Node *q = new Node; 31 q->d = e; 32 q->next = NULL; 33 if(p == NULL) 34 Link[s].next = q; 35 else 36 { 37 while(k--) 38 p = p->next; 39 p->next = q; 40 } 41 Link[s].num++; 42 } 43 void Delete(Node *p) 44 { 45 if(p == NULL) 46 return ; 47 Delete(p->next); 48 delete p; 49 } 50 51 void clean(LinkList *Link,int n) 52 { 53 for(int i = 0;i < n;++i) 54 Delete(Link[i].next); 55 } 56 57 void dfs(LinkList *head,int l,int deep) 58 { 59 length[l] = deep; 60 visit[l] = 1; 61 int k = head[l].num; 62 Node *p = head[l].next; 63 while(p != NULL) 64 { 65 if(visit[p->d] == 0) 66 dfs(head,p->d,deep+1); 67 p = p->next; 68 } 69 } 70 71 int main() 72 { 73 int T,n,d,a,b; 74 scanf("%d",&T); 75 while(T--) 76 { 77 LinkList Link[maxn]; 78 scanf("%d%d",&n,&d); 79 for(int i = 1;i<n;++i) 80 { 81 scanf("%d%d",&a,&b); 82 push(Link,a,b); 83 push(Link,b,a); 84 } 85 memset(length,0,sizeof(length)); 86 memset(visit,0,sizeof(visit)); 87 dfs(Link,0,0); 88 int tot = 0; 89 for(int i = 1;i < n;++i) 90 if(length[i] > d) 91 tot++; 92 printf("%d ",tot); 93 clean(Link,n); 94 } 95 return 0; 96 }
一维数组AC代码:
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 using namespace std; 5 6 const int maxn = 100005; 7 int len[maxn]; 8 9 int main() 10 { 11 int T,n,d,s,e; 12 scanf("%d",&T); 13 while(T--) 14 { 15 scanf("%d %d",&n,&d); 16 memset(len,0,sizeof(len)); 17 for(int i = 1;i < n;++i) 18 { 19 scanf("%d %d",&s,&e); 20 if(len[s]) len[e] = len[s] + 1; 21 else if(s == 0) len[e] = 1; 22 else ; 23 } 24 int tot = 0; 25 for(int i = 1;i < n;++i) 26 if(len[i] > d) 27 tot++; 28 printf("%d ",tot); 29 } 30 return 0; 31 }