Algorithm 遍历euler回路中的所有边和打印节点
我正在努力解决这个问题。 我可以通过观察给定结构是否可以形成euler回路来找到,但我无法找出如何找到给定测试用例的所有路径 五, 2.1 2.2 34 3.1 2 4 在节点2的电路中有一个循环,我不知道如何跟踪,如果我使用邻接列表表示,那么我将得到以下列表 1:2,3 2:1,2,2,4 3:1,4 4:2,3 所以,如何遍历每一条边,我知道这是欧拉回路的问题,但自循环的事情让我很难编写代码,我没有从任何教程或博客中了解这件事 我再次考虑过在遍历路径后从邻接列表中删除节点(为了维护euler的属性(路径应该遍历一次)),但我使用vector存储邻接列表,我不知道如何从vector中删除特定元素。我在谷歌上搜索了一下,找到了要从向量中删除的Algorithm 遍历euler回路中的所有边和打印节点,algorithm,data-structures,graph,graph-algorithm,Algorithm,Data Structures,Graph,Graph Algorithm,我正在努力解决这个问题。 我可以通过观察给定结构是否可以形成euler回路来找到,但我无法找出如何找到给定测试用例的所有路径 五, 2.1 2.2 34 3.1 2 4 在节点2的电路中有一个循环,我不知道如何跟踪,如果我使用邻接列表表示,那么我将得到以下列表 1:2,3 2:1,2,2,4 3:1,4 4:2,3 所以,如何遍历每一条边,我知道这是欧拉回路的问题,但自循环的事情让我很难编写代码,我没有从任何教程或博客中了解这件事 我再次考虑过在遍历路径后从邻接列表中删除节点(为了维护euler
remove
命令,但是remove
从向量中删除了所有匹配的元素
我现在试图解决以下问题,但得到了WA:(
#包括
#包括
#包括
int G[52][52];;
int[52],n;
void printadj(){
int i,j;
对于(i=0;i你需要做的是形成任意循环,然后将所有循环连接在一起。你似乎只做了一次深度优先遍历,这可能会给你一个欧拉回路,但也可能给你一个欧拉回路的“捷径”。这是因为在欧拉回路经过多次的每个顶点上(即,当深度优先遍历第一次到达该处时,它可以拾取直接返回深度优先遍历起点的边
因此,您的算法应该由两部分组成:
查找所有周期
将循环连接在一起
如果操作正确,您甚至不必检查所有顶点的阶数是否为偶数,相反,您可以依赖这样一个事实:如果步骤1或2无法继续,则不存在欧拉循环
参考实现(Java)
由于您的问题中没有语言标记,我假设我给您一个Java参考实现对您来说很好。此外,我将使用术语“node”而不是“vertex”,但这只是个人偏好(它提供了较短的代码;))
我将在该算法中使用一个常量,我将从其他类中引用该常量:
公共静态最终整数节点数=50;
然后,我们需要一个Edge类来轻松构建循环,循环基本上是边的链接列表:
公共类边缘
{
INTU,v;
边缘上一个,下一个;
公共边缘(int u,int v)
{
这个。u=u;
这个,v=v;
}
/**
*将新边附加到此边,从而指向给定节点
*并返回新创建的边
*附加的边开始不需要指定,因为它会指定
*始终是此边结束的节点。
*
*@param node附加边结束的节点。
*/
公共边缘附加(int节点)
{
next=新边(此.v,节点);
next.prev=这个;
下一步返回;
}
}
然后,我们需要一个可以轻松连接两个循环的Cycle类:
公共类循环
{
边缘启动;
boolean[]used=新的boolean[节点数+1];
公共自行车(边缘起步)
{
//存储循环本身
this.start=start;
//并记住此循环中使用的节点
使用的[start.u]=true;
对于(边e=start.next;e!=start;e=e.next)
已用[e.u]=真;
}
/**
*检查此循环是否可以与给定的循环联接。即
*当且仅当两个循环使用公共节点时的情况。
*
*@return{@code true}如果这个循环和那个循环可以合并,
*{@code false}否则。
*/
公共布尔canJoin(循环)
{
//查找常用节点
对于(int节点=1;节点1)
{
//将最后一个周期与之前的任何一个周期合并
Cycle last=cycles.removeLast();
对于(周期电流:周期)
if(当前可加入(最后一个))
{
//找到一个!只需加入它并继续合并
当前连接(最后);
继续合并;
}
//没有找到兼容的循环,这意味着没有欧拉循环
返回null;
}
返回cycles.getFirst();
}
你需要做的是形成任意循环,然后将所有循环连接在一起。你似乎只做了一次深度优先遍历,这可能会给你一个欧拉回路,但也可能给你一个欧拉回路的“捷径”。这是因为在欧拉回路经过多次的每个顶点上(即,当深度优先遍历第一次到达该处时,它可以拾取直接返回深度优先遍历起点的边
因此,您的算法应该由两部分组成:
查找所有周期
将循环连接在一起
如果操作正确,您甚至不必检查所有顶点的阶数是否为偶数,相反,您可以依赖这样一个事实:如果步骤1或2无法继续,则不存在欧拉循环
参考实现(Java)
由于您的问题中没有语言标记,我假设我给您一个Java参考实现对您来说很好。此外,我将使用术语“node”而不是“vertex”,但这只是个人偏好(它提供了较短的代码;))
我将在该算法中使用一个常量,我将从其他类中引用该常量:
公共静态最终整数节点数=50;
那么,我们需要一个Edg
#include<iostream>
#include<cstdio>
#include<cstring>
int G[52][52];
int visited[52],n;
void printadj() {
int i,j;
for(i=0;i<51;i++) {
for(j=0;j<51;j++)
printf("%d ",G[i][j]);
printf("\n");
}
}
void dfs(int u){
int v;
for(v=0;v<51;v++){
if(G[u][v]){
G[u][v]--;
G[v][u]--;
printf("%d %d\n",u,v);
dfs(v);
}
}
}
bool is_euler(){
int i,j,colsum=0,count=0;
for(i=0;i<51;i++) {
colsum=0;
for(j=0;j<51;j++) {
if(G[i][j] > 0) {
colsum+=G[i][j];
}
}
if(colsum%2!=0) count++;
}
// printf("\ncount=%d\n",count);
if(count >0 ) return false;
else return true;
}
void reset(){
int i,j;
for(i=0;i<51;i++)
for(j=0;j<51;j++)
G[i][j]=0;
}
int main(){
int u,v,i,t,k;
scanf("%d",&t);
for(k=0;k<t;k++) {
scanf("%d",&n);
reset();
for(i=0;i<n;i++){
scanf("%d%d",&u,&v);
G[u][v]++;
G[v][u]++;
}
// printadj();
printf("Case #%d\n",k+1);
if(is_euler()) {
dfs(u);
}
else printf("some beads may be lost\n");
printf("\n");
}
return 0;
}
#include<iostream>
#include<cstdio>
#include<cstring>
#define max 51
int G[max][max],print_u[max],print_v[max],nodes_traversed[max],nodes_found[max];
int n,m;
void printadj() {
int i,j;
for(i=0;i<max;i++) {
for(j=0;j<max;j++)
printf("%d ",G[i][j]);
printf("\n");
}
}
void dfs(int u){
int v;
for(v=0;v<50;v++){
if(G[u][v]){
G[u][v]--;
G[v][u]--;
print_u[m]=u;
print_v[m]=v;
m++;
dfs(v);
}
}
nodes_traversed[u]=1;
}
bool is_evendeg(){
int i,j,colsum=0,count=0;
for(i=0;i<50;i++) {
colsum=0;
for(j=0;j<50;j++) {
if(G[i][j] > 0) {
colsum+=G[i][j];
}
}
if(colsum&1) return false;
}
return true;
}
int count_vertices(int nodes[]){
int i,count=0;
for(i=0;i<51;i++) if(nodes[i]==1) count++;
return count;
}
void reset(){
int i,j;
m=0;
for(i=0;i<max;i++)
for(j=0;j<max;j++)
G[i][j]=0;
memset(print_u,0,sizeof(print_u));
memset(print_v,0,sizeof(print_v));
memset(nodes_traversed,0,sizeof(nodes_traversed));
memset(nodes_found,0,sizeof(nodes_found));
}
bool is_connected(int tot_nodes,int trav_nodes) {
if(tot_nodes == trav_nodes) return true;
else return false;
}
int main(){
int u,v,i,t,k,tot_nodes,trav_nodes;
scanf("%d",&t);
for(k=0;k<t;k++) {
scanf("%d",&n);
reset();
for(i=0;i<n;i++){
scanf("%d%d",&u,&v);
G[u][v]++;
G[v][u]++;
nodes_found[u]=nodes_found[v]=1;
}
// printadj();
printf("Case #%d\n",k+1);
tot_nodes=count_vertices(nodes_found);
if(is_evendeg()) {
dfs(u);
trav_nodes=count_vertices(nodes_traversed);
if(is_connected(tot_nodes,trav_nodes)) {
for(i=0;i<m;i++)
printf("%d %d\n",print_u[i],print_v[i]);
}
else printf("some beads may be lost\n");
}
else printf("some beads may be lost\n");
printf("\n");
}
return 0;
}