最小DFS序

 

时间限制:1秒        内存限制:128M

题目描述

一般来讲,我们在对树进行深度优先遍历时,对于每个节点,在刚进入递归后以及即将回溯前各记录一次该节点的编号,最后产生一个长度为2n的节点的序列就称为树的DFS序。

输入描述

第一行,两个整数n(1<=n<=1000),s,其中n表示树的节点的个数,s表示树的根节点的编号。

接下来的n-1行中,每行有两个整数x,y,表示x和y有一条边

输出描述

输出一组字典序最小的DFS序,每两个数字之间用空格隔开。

样例

输入

9 1
1 2
1 7
1 4
2 8
2 5
4 6
4 3
3 9

输出

1 2 5 5 8 8 2 4 3 9 9 3 6 6 4 7 7 1
#include<bits/stdc++.h>
using namespace std;
const int N=2005;
int head[N],vis[N],ver[N],Next[N],tot=-1,n,S;
struct node{
	int x,y;
}s[2005];
bool cmp(node a,node b){
	if(a.x!=b.x){
		return a.x<b.x;
	}
	return a.y>b.y;
}
void Add(int x,int y){
	ver[++tot]=y;
	Next[tot]=head[x];
	head[x]=tot;
}
void dfs(int pos){
	vis[pos]=1;
	cout<<pos<<" ";
	for(int i=head[pos];i!=-1;i=Next[i]){
		int ljd=ver[i];
		if(vis[ljd]==0){
			dfs(ljd);
		}
	}
	cout<<pos<<" ";
}
int main(){
	cin>>n>>S;
	memset(head,-1,sizeof(head));
	for(int i=1;i<2*n;i+=2){
		cin>>s[i].x>>s[i].y;
		s[i+1].x=s[i].y;
		s[i+1].y=s[i].x;
	}
	sort(s+1,s+2*n-1,cmp);
	for(int i=1;i<2*n;i++){
		Add(s[i].x,s[i].y);
	}
	dfs(S);
	return 0;
} 

### 定义 在图论中,若图G中的一个回路包括每个边恰好一次,则该回路称为欧拉回路。而最小字典欧拉回路是在所有可能的欧拉回路中,按照顶点的字典排列后,字典最小的那个欧拉回路。例如,对于顶点编号为1、2、3的图,回路(1, 2, 3, 1)和(2, 1, 3, 2),若按字典比较,(1, 2, 3, 1)的字典更小,如果它是欧拉回路,那么它就是最小字典欧拉回路。 ### 算法 寻找最小字典欧拉回路通常可以使用Hierholzer算法进行改进。Hierholzer算法的基本思想是从一个起始顶点开始,进行深度优先搜索(DFS),直到无法继续前进,将经过的边标记为已访问,然后将路径上的顶点依次记录下来。为了得到最小字典的欧拉回路,在每一步选择下一个顶点时,优先选择编号最小的未访问的邻接顶点。 ### 实现 以下是使用Python实现的寻找最小字典欧拉回路的代码示例: ```python from collections import defaultdict def hierholzer(graph, start): stack = [start] circuit = [] while stack: vertex = stack[-1] if graph[vertex]: next_vertex = min(graph[vertex]) graph[vertex].remove(next_vertex) graph[next_vertex].remove(vertex) stack.append(next_vertex) else: circuit.append(stack.pop()) return circuit[::-1] # 示例图的邻接表表示 graph = defaultdict(list) edges = [(1, 2), (2, 3), (3, 1)] for u, v in edges: graph[u].append(v) graph[v].append(u) start_vertex = 1 euler_circuit = hierholzer(graph, start_vertex) print("最小字典欧拉回路:", euler_circuit) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值