题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=20
题目分析:其实上就是对输入的节点,建立一张图。由于这里的节点数比较大,所以不可能用二维的数组来保存邻接矩阵,这里用链表来描述邻接边。也就是说如果节点s,e相邻,那么在edge[e]后面加入终点为s的边,同样在edge[s]后面加入终点为e的边。然后采用广度优先遍历,因为第一次通过某个节点s访问到节点e,则节点s一定是节点e必然会通过的边。
参考代码:
#include<stdio.h> #include<malloc.h> #include<string.h> typedef struct Node { int e; Node *next; }; Node edge[100001]; int flag[100001]; int queue[100001]; int AddEdge(Node *edge, int s, int e)//把连接s,e的边加到对应的边链表中 { Node *p = (Node *)malloc(sizeof(Node *)); if(!p) return 1; p->e = e; p->next = edge[s].next; edge[s].next = p; p = (Node *)malloc(sizeof(Node *)); if(!p) return 1; p->e = s; p->next = edge[e].next; edge[e].next = p; return 0; } void Destory(Node *edge, int n)//销毁边的链表 { Node *p; for(int i = 1; i <= n; ++i) { p = edge[i].next; while(p) { edge[i].next = p->next; free(p); p = edge[i].next; } } } int main() { int a,b; int n,s; int i,t; int head,tail; Node *p; scanf("%d", &t); while(t--) { scanf("%d %d",&n,&s); memset(flag,0,sizeof(flag)); memset(edge,0,sizeof(edge)); for(i = 1; i < n; ++i) { scanf("%d %d",&a, &b); if(AddEdge(edge, a, b)) break; } queue[0] = s; head = 0; tail = 1; flag[s] = 1; while(head <= tail) { p = edge[queue[head]].next; while(p) { //如果该点没有访问过,设访问标记,加入队列 if(!flag[p->e]) { queue[++tail] = p->e; flag[p->e] = queue[head]; } p = p->next; } ++head; } flag[s] = 0; for(i = 1; i < n; ++i) { if(flag[i]) printf("%d ",flag[i]); else//如果某些节点时孤立点,那么直接输出-1 printf("-1 "); } if(flag[i]) printf("%d\n",flag[i]); else printf("-1\n"); } Destory(edge,n); }