欧拉回路

图中所有边一次仅且一次行便所有顶点的通路称作欧拉通路。
图中所有边一次仅且一次行便所有顶点的回路称作欧拉回路。

判断无向图G存在欧拉通路:
G为连通图,并且G仅有两个奇度顶点(度数为奇数的顶点)或者无奇度顶点。
(1)G仅有两个奇度顶点时,G的欧拉通路以此两个结点为端点。
(2)G无奇度顶点时,G必有欧拉回路。

判断有向图D存在欧拉通路:
D为连通图,
(1)图D除两个顶点外,其余顶点的出度与入度都相等。特殊的两点一个顶点的出度与入度之差为1(始点),另一个顶点的出度与入度之差为-1(终点),D为欧拉通路。
(2)D的所有顶点的出、入度都相等时,D中存在欧拉回路。

方法求解:
1、DFS暴搜

例题 The Necklace UVA - 10054
数据:
Sample Input
2
5
1 2
2 3
3 4
4 5
5 6
5
2 1
2 2
3 4
3 1
2 4
Sample Output
Case #1
some beads may be lost
Case #2
2 1
1 3
3 4
4 2
2 2

#include <bits/stdc++.h>
using namespace std;
const int maxn=55;
int Max=-9999, Min=9999;
int ma[maxn][maxn];
int m, n, k=0;
int in[maxn];
int ans[100005][2];

void dfs(int x)
{
    int i;
    for(i=Min; i<=Max; i++)
    {
        if(ma[x][i]!=0)//从任意一个与它相连的边出发
        {
//            cout<<x<<" "<<i<<endl;
            ma[x][i]--;
            ma[i][x]--;//删除遍历完的边
            dfs(i);
            ans[++k][0]=x;//记录路径
            ans[k][1]=i;
        }
    }
}

int main()
{
    int T;
    scanf("%d",&T);
    for(int p=1; p<=T; p++)
    {
        int n;
        k=0;
        Max=-9999;
        Min=9999;//初始化
        scanf("%d",&n);
        memset(ma, 0, sizeof(ma));
        memset(in, 0, sizeof(in));
        memset(ans, 0, sizeof(ans));//初始化
        for(int i=0; i<n; i++)
        {
            int x, y;
            scanf("%d %d",&x, &y);
            ma[x][y]++;
            ma[y][x]++;
            Max=max(Max, max(x, y));
            Min=min(Min, min(x, y));
            in[x]++;
            in[y]++;
        }
        int flag=1;
        for(int i=Min; i<=Max; i++)//从数据中的最小值到最大值
        {
            if(in[i]%2==1)//若存在奇点则不是欧拉回路
            {
                flag=0;
                break;
            }
        }
        if(flag)
        {
            dfs(Min);
        }
        if(k!=n) flag=0;//若图没有走完说明不是连通图
        printf("Case #%d\n",p);
        if(flag==0)
            printf("some beads may be lost\n");
        else
        {
            for(int i=k; i>=1; i--)
            {
                printf("%d %d\n",ans[i][0],ans[i][1]);
            }
        }
        if(p!=T)
            printf("\n");
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值