欧拉图

通过有向图或者无向图中所有边且每边只通过一次的路称为欧拉通路,相应的回路称为欧拉回路,具有欧拉回路的图称为欧拉图,具有欧拉通路的图称为半欧拉图

1.无向连通图G是欧拉图,当且仅当G不含奇数度结点(G的所有结点度数为偶数);
2.无向 连通图G含有欧拉通路,当且仅当G有零个或两个 奇数度的结点;
3.有向连通图D是欧拉图,当且仅当该图为连通图且D中每个结点的入度=出度
4.有向连通图D含有欧拉通路,当且仅当该图为连通图且D中除两个结点外,其余每个结点的入度=出度, ,只有一个点,出度比       入度大1,这个点一定是起点; 一个点,入度比出度大1,这个点一定是终点.其余点的出度等于入度

   (注意,只能大1,而且这样的点分别只能有1个,而且存在起点就一定要存在终点,存在终点就一定要存在起点)



一个图如何使欧拉图呢,首先判断它要是连通的


判断有向图是否存在欧拉路径(poj1386)

题意:给你n个单词,要求这些单词相连,要求是前面的字母的尾字母和后面单词的头字母相同,问你这n个单词能不能全部连起来,可以连成一条链或者连成一个环

另外单词只有小写字母。很容易想到,顶点集合就是26个小写字母,用1到26来表示,一个单词的首字母和尾字母就是一条有向边,注意是有向边,因为单词是不能倒回来的

其实就是问你这个图是否存在欧拉道路(一条链的情况)或者欧拉回路(环的情况),反正存在欧拉路就是成功的,否则就是失败

#include <iostream>

#include <stdio.h>

#include <string.h>

#include <algorithm>

using namespace std;

int chu[30],ru[30],wuxiang[30][30],via[30];

void cha(int i)

{

    for(int j=1;j<=26;j++)

    {

        if(wuxiang[i][j]==1&&via[j]==0)

        {

            via[j]=1;

            cha(j);

        }

    }

}

int liantong()

{

    // printf("@\n");

    for(int i=1;i<=26;i++)

    {

        if(ru[i]!=0||chu[i]!=0)

        {

            cha(i);

            break;

        }

    }

    for(int i=1;i<=26;i++)

    {

        if(ru[i]!=0||chu[i]!=0)

        {

            if(via[i]==0)

                return 0;

        }

    }

    return 1;

}

int oula()

{

    //printf("\n");

    int r=0,c=0,i;

    for(i=1;i<=26;i++)

    {

        if(ru[i]!=0||chu[i]!=0)

        {

            if(ru[i]-chu[i]==1)

            {

                r++;

                if(r>1)

                    break;

            }

            else if(chu[i]-ru[i]==1)

            {

                c++;

                if(c>1)

                    break;

            }

            else if(chu[i]-ru[i]>1||ru[i]-chu[i]>1)

                break;

        }

    }

    if(i<=26)

        return 0;

    // printf("-\n");

    return 1;

}

int main()

{

    int T,n,a,b;

    char s[1005];

    int str;

    scanf("%d",&T);

    for(int j=0;j<T;j++)

    {

        memset(via,0,sizeof(via));

        memset(chu,0,sizeof(chu));

        memset(ru,0,sizeof(ru));

        memset(wuxiang,0,sizeof(wuxiang));

        scanf("%d",&n);

        for(int i=0;i<n;i++)

        {

            scanf("%s",s);

            str=strlen(s);

            a=s[0]-'a'+1;

            b=s[str-1]-'a'+1;

            chu[a]++;

            ru[b]++;

            wuxiang[a][b]=wuxiang[b][a]=1;

            

        }

        if(liantong()&&oula())

        {

            // printf("|\n");

            printf("Ordering is possible.\n");

        }

        else

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

        

    }

    return 0;

}

看到有人用DFS判断是否连通

下面说一个进化版,poj1300,Door man,有N个房间,每个房间有几个门,给出一个人目前的房间号M,然后判断他能不能路过每一个门,每个门只能过一次,最后回到0点。要达成这样的结果又两种方式,第一种起点在零点,每个房间有偶数个门,第二种只有起点和0点不是偶数

这道题有sscan的用法

//

//  main.cpp

//  B.p1300

//

//  Created by Mr.Xue on 17/2/9.

//  Copyright © 2017 Mr.Xue. All rights reserved.

//


#include <iostream>

#include <string.h>

#include <stdio.h>

using namespace std;

int readline(char *s)

{

    int L;

    for(L=0;(s[L]=getchar())!='\n'&&s[L]!=EOF;L++);

    s[L]=0;

    return L;

}

int main()

{

    int i,j,M,N,doors;

    char buf[500];

    int door[21];

    while(!readline(buf))

    {

        if(buf[0]=='S')

        {

            memset(door,0,sizeof(door));

            sscanf(buf,"%*s %d %d",&M,&N);

            doors=0;

            for(i=0;i<N;i++)

            {

                readline(buf);

                int k=0;

                while(sscanf(buf+k,"%d",&j)==1)

                {

                    while(buf[k]&&buf[k]==' ')

                        k++;

                    door[i]++;

                    door[j]++;

                    doors++;

                }

            }

            readline(buf);

            int ji=0;

            for(i=0;i<N;i++)

            {

                if(door[i]%2!=0)

                    ji++;

            }

            if(M==0&&ji==0)

                printf("Yes%d\n",doors);

            else if(ji==2&&door[0]%2!=0&&door[M]%2!=0&&M!=0)

                printf("Yes%d\n",doors);

            else

                printf("N0\n");

        }

        else if( !strcmp(buf, "ENDOFINPUT") )

            break;

        

    }

    //cout << "Hello, World!\n";

    return 0;

}



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值