//使用非递归栈模拟深度遍历,否则此题用递归深搜会栈溢出
//本题的题意其实就是找出一棵树中所有最长路径的端点
//只需要遍历两次即可找到长度最长的路径的所有端点
//第一次遍历从任意一点开始,记录以这个点为起点的最长路径的尾端点(可能不止一个)
//第二次遍历从第一次的尾端点中任选一个为起点,再次记录此次遍历过程中最长路径的尾端点
//两次遍历的尾端点放在一块就是整个树中,最长路径的所有端点了
//(注意,第一次遍历和第二次遍历中记录的尾端点可能有重合,当第一次遍历起点恰好是最长路径中点时,便会重合)
//ac
#define MAXN 10000
#include<stdio.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;
struct Node{
int neighbors[MAXN]; //结点的邻居
int visIdx; //结点已访问到的邻居的下标
int size; //结点的邻居数
};
struct Stack{
//栈
int data[MAXN]; //存放nodes数组下标
int top; //指向栈顶元素的下一个,初始为0
};
struct Gather{
//记录尾端点的集合
int data[MAXN]; //存放nodes数组下标
int size; //尾端点数,初始为0
//路径长度,初始为0 当遍历到一路径的长度比dph大时,更新dph,清空data,并加入尾端点
//当遍历到一路径的长度等于dph时,直接把尾端点加入到data中
int dph;
};
Node* nodes[MAXN]; //所有结点
bool visited[MAXN]; //访问标志数组
Stack s;
Gather gat1; //存放第一次遍历的尾端点
Gather gat2; //存放第二次遍历的尾端点
void traversal(int st,Gather* gat){
//使用栈的深度遍历,从st开始的最长路径的尾端点会被记录在gat中
/*
这种遍历都是一个套路!!
先入栈一个起点,然后当栈不空时一个大循环
循环里面
第一:访问栈顶元素(visited=true),检查栈顶元素是否命中,命中了就怎么怎么样啊巴拉巴拉,
这个根据自己想做什么自己写
第二:寻找栈顶元素的下一个访问元素,就是找栈顶元素的没访问过的下一个邻居,用node->visIdx记录访问到哪一个邻居了
用visited检擦这个一邻居有没有访问过
第三:如果我的邻居全部都访问完了(node->visIdx==node->size),那就弹出栈顶元素(top--);否则入栈我找到的这个邻居
*/
s.top=0;
s.data[s.top++]=st; //起点入栈
while(s.top!=0){
//当栈不