欧拉图

定义

欧拉通路
  • 图中行遍所有顶点且恰好经过图中的每条边一次的通路. 顶点可以重复经过,边只经过一次。
欧拉回路
  • 图中行遍所有顶点且恰好经过图中的每条边一次的回路. 顶点可以重复经过,边只经过一次。
欧拉图:
  • 有欧拉回路的图
半欧拉图
  • 有欧拉通路而无欧拉回路的图.

几点说明:

  1. 上述定义对无向图和有向图都适用.
  2. 规定平凡图为欧拉图.$\ \ \ \ $ 平凡图: 1 阶零图,即只有1个顶点没有边的图
  3. 欧拉通路是简单通路, 欧拉回路是简单回路.
  4. 环不影响图的欧拉性.


图中, \((1), (4)\)为欧拉图; \((2), (5)\)为半欧拉图; \((3),(6)\)既不是欧拉图, 也不是半欧拉图.

判定

无向欧拉图
  • 无向图\(G\)为欧拉图当且仅当\(G\)连通且无奇度顶点.
无向半欧拉图
  • 无向图\(G\)是半欧拉图当且仅当\(G\)连通且恰有两个奇度顶点.
有向欧拉图
  • 有向图\(D\)是欧拉图当且仅当\(D\)连通且每个顶点的入度都等于出度.
有向半欧拉图
  • 有向图D具有欧拉通路当且仅当D连通且恰有两个奇度顶点, 其中一个入度出度\(1\)(终点), 另一个出度入度\(1\)(起点), 其余顶点的入度等于出度.

HDU-1878-无向图欧拉回路

#include<bits/stdc++.h>
using namespace std;
const int M=1010;
int edge[M][M];
int vis[M];
int du[M];
int n,m;
void init( )
{
    memset(edge,0,sizeof(edge));
    memset(vis,0,sizeof(vis));
    memset(du,0,sizeof(du));
}
void dfs(int x)//判断是否连通
{
    vis[x]=1;
    for(int i=1;i<=n;i++)
    {
        if(!vis[i]&&edge[x][i])
        {
            dfs(i);
        }
    }
}
int cheak(int n)//查找多少个顶点的度是否是奇数
{
    int ans=0;
    for(int i=1;i<=n;i++)
    {
        if(du[i]%2!=0)
        {
            ans++;
        }
    }
    return ans;
}
int main( )
{
    int x,y;
    while(~scanf("%d%d",&n,&m)&&n)
    {
        init( );
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&x,&y);
            edge[x][y]=edge[y][x]=1;
            du[x]++;
            du[y]++;
        }
        dfs(1);
        int flag=1;
        for(int i=1;i<=n;i++)
        {
            if(!vis[i])
            {
                flag=0;
                break;
            }
        }
        if(!cheak(n)&&flag)
        {
            printf("1\n");
        }
        else
        {
            printf("0\n");
        }
    }
    return 0;
}

POJ-1386-(有向图)Play on Words

  • 每个单词的第一个字母到最后一个字母有一条有向边,构图
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int edge[26][26];
char s[1010];
// int out[26];
// int in[26];
int du[26];
int vis[26];
int use[26];
int n;
void dfs(int x)
{
    vis[x]=1;
    for(int i=0; i<26; i++)
    {
        if(edge[x][i]&&!vis[i])
        {
            dfs(i);
        }
    }
}
int main( )
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        getchar( );
        // memset(out,0,sizeof(out));
        // memset(in,0,sizeof(in));
        memset(use,0,sizeof(use));
        memset(edge,0,sizeof(edge));
        memset(du,0,sizeof(du));
        while(n--)
        {
            scanf("%s",s);
            getchar( );
            int len=strlen(s);
            int u=s[0]-'a';
            int v=s[len-1]-'a';
            edge[u][v]=1;
            // out[u]++;
            // in[v]++;
            du[u]--;//出度为减
            du[v]++;//入度为加
            use[u]=1;
            use[v]=1;
        }
        int x=-1;
        int flag1=0;
        int flag2=0;
        for(int i=0; i<26; i++)
        {
            if(!use[i])
            {
                continue;
            }
            else if(du[i]==0)
            {
                if(x==-1)
                {
                    x=i;
                }
            }
            else if(du[i]==-1)
            {
                flag1++;
                x=i;
                if(flag1>1)
                {
                    break;
                }
            }
            else if(du[i]==1)
            {
                flag2++;
                if(flag2>1)
                {
                    break;
                }

            }
            else
            {
                flag1=flag2=-1;
                break;
            }
            // else if(out[i]==in[i])
            // {
            //     if(x==-1)
            //     {
            //         x=i;
            //     }

            // }
            // else if(out[i]-in[i]==1)
            // {
            //     flag1++;
            //     x=i;
            //     if(flag1>1)
            //     {
            //         break;
            //     }
            // }
            // else if(in[i]-out[i]==1)
            // {
            //     flag2++;
            //     if(flag2>1)
            //     {
            //         break;
            //     }
            // }
            // else
            // {
            //     flag1=flag2=-1;
            //     break;
            // }
        }
        if((flag1==1&&flag2==1)||(flag1==0&&flag2==0))//两者为0,欧拉回路,两者为1,欧拉通路
        {
            int flag=0;
            memset(vis,0,sizeof(vis));
            dfs(x);
            for(int i=0; i<26; i++)
            {
                if(!vis[i]&&use[i])
                {
                    flag=1;
                    break;
                }
            }
            if(flag==1)
            {
                printf("The door cannot be opened.\n");
            }
            else
            {
                printf("Ordering is possible.\n");
            }

        }
        else
        {
            printf("The door cannot be opened.\n");
        }

    }
    return 0;
}
posted @ 2020-06-15 22:56  私の目を見て  阅读(670)  评论(0编辑  收藏  举报