uva 10054--The Necklace

本文介绍了一个用于解决UVA10054问题的算法实现,该问题涉及欧拉回路的计算,并通过并查集验证图的连通性。代码实现了寻找欧拉回路的过程,并确保图的每条边被遍历一次且仅一次。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

//
//  main.cpp
//  uva 10054 - The Necklace
//
//  Created by XD on 15/7/21.
//  Copyright (c) 2015年 XD. All rights reserved.
//
#include <iostream>
#include <string>
#include <queue>
#include <stack>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <vector>
#include <string.h>
#include <string>
#include <algorithm>
#include <set>
#include <map>
#include <cstdio>
using namespacestd ;

//用来寻找路径

int visit[55][55] ;
int g[55][55];
int d[55] ;
struct edge{
    int u ;
    int v  ;
};

//用来存储路径

stack<edge>  eulerpath ;

//欧拉回路算法,使用递归的思想
 void  euler(int s)
{
    
    for (int i = 1 ; i < 51 ; i++) {
        if (g[s][i]) {
            g[s][i]--;g[i][s]--;
            edge temp ; temp.u = s ; temp.v = i ;
            /*以下两步顺序很重要,先使用递归查找所有的圈,这样就可以找到欧拉路径
             以下是详细解释
             思想是先将在将来访问到的节点可能的圈给压入栈中,然后就可以将当前的边压入栈中,这样根据栈的先进后出的特点,就可以直接打印出欧拉路径,当然也可以使用数组,因为这是无向图,所以无方向,但是对于有向图,则用栈(主要省去了不必要的逆序打印的麻烦)
             */
            euler(i)  ;
            eulerpath.push(temp) ;
        }
    }
}

//并查集判断连通性
int p[55] ;
int r[55] ;
void init()
{
    for (int i = 0 ; i < 51;  i++) {
        p[i]= i ;
        r[i] = 0 ;
    }
}
//并查集的三个函数,使用了rank(秩,算法导论书上的),和路径压缩
int find_set(int x)
{
    
    if (p[x]!=x) {
        p[x] =find_set(p[x]) ;
    }
    
    
    returnp[x] ;
}

void link(int x ,int y )
{
    if (r[x] <r[y]) {
        p[x] =p[y] ;
    }
    else
    {
        p[y] = x ;
        if (r[x] ==r[y]) {
            r[x] += 1 ;
        }
    }
}

void UnionSet(int x ,int y)
{
    link(find_set(x) ,find_set(y)) ;
}

//
set<int> node ;


int main(int argc,const char * argv[]) {
    int casenum ;
    scanf("%d" ,&casenum) ;
    int  u , v ;
    int n  ;
    int j = 0;
    
    while (casenum--) {
        while (!eulerpath.empty()) {
            eulerpath.pop() ;
        }
        init() ;
        memset(g, 0,sizeof(g)) ;
        memset(visit, 0,sizeof(visit)) ;
        memset(p, 0,sizeof(p)) ;
        memset(r,0,sizeof(r)) ;
        node.clear() ;
        memset(d, 0,sizeof(d)) ;
        scanf("%d" ,&n) ;
        for (int i = 0 ; i < n; i++) {
            scanf("%d%d" ,&u,&v) ;
            UnionSet(u,  v) ;
            node.insert(u) ;node.insert(v) ;
            g[u][v]++ ;g[v][u]++; ;
            d[u]++ ;d[v]++ ;
        }
        
        int flag = -1 ;
        int start =0;
        for (set<int >::iterator it = node.begin() ; it!=node.end(); it++) {
            start = *it  ;
            if (d[*it]%2==1)  {
                flag = -2 ;
                break ;
            }
            if (flag==-1) {
                flag = find_set(*it) ;
            }
            else{
                if (flag!=find_set(*it)) {
                    flag = -2 ;
                    break ;
                }
            }
        }
        
        printf("Case #%d\n" , ++j)  ;
        if (flag ==-2) {
            printf("some beads may be lost\n") ;
        }
        else{
            euler(start) ;
            while (!eulerpath.empty()) {
                edge temp =eulerpath.top() ;eulerpath.pop() ;
                printf("%d %d\n" ,temp.u,temp.v) ;
            }
        }
        
        if (casenum> 0 ) {
            printf("\n") ;
        }
    }
    return 0;
}






















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值