欧拉回路

一,定理及推论

      1,无向图存在欧拉通路的充要条件,为连通图,仅存在两个奇度节点,或无奇度结点

      2,无向图存在欧拉回路的条件,为连通图,不存在奇度点


     3,有向图存在欧拉通路的条件,连通,所有点的出度等于入度,或仅存在两个顶点出度不等于入度,出、入度之          差为1的为起点,出入度之差为-1的为终点

     4,有向图存在欧拉回路的条件,连通,所有点的出度等于入度


二 、欧拉图的判定

     题目链接:点击打开链接

     无向图判断是否存在欧拉回路

     1.是连通图     2.无奇数度的点

     连通图的判断可以用并查集,判断有误奇数点只要用一个数组记录就可以

     向图判断是否存在欧拉回路

     1.是连通图    2,所有点的出度等于入度

      与无向图类似,区别在于用两个数组分别记录顶点的出度数和入度数


三、欧拉通路的判定

      题目链接

             题意:
             一幅无向图,每条边只能经过一次,需要几次才能经过所有的边
            输入n,m,n个点,m条边接着m行数据每行表示起点和终点

        思路:一副连通的图,有几对奇数点度,就要相应的次数遍历完
                 1.需要判断有几幅连通图,单源点应该排除,输入的时候
                  不输入
                 2.每一幅图判断几对奇数点,奇数点个数除 2 等于
                 需要遍历的次数

代码:

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int od[100005];//记录节点度数
int father[100005];//父节点
int rk[100005];//优化
int vis[100005];//记录父节点
int num[100005];//连通图奇数度节点个数


int find(int x)
{
   if (x!=father[x])
   return find(father[x]);
   else
   return x;
}

void hebing(int x,int y)
{
   if (rk[x]>rk[y])
   {
      father[x]=y;
   }
   else
   {
      father[y]=x;
      if (rk[x]==rk[y])
      rk[x]++;
   }
}

int main()
{
   int n,m,sum;
   int i,j,k,a,b;
   while (~scanf ("%d %d",&n,&m))
   {
      sum=0;
      memset(od,0,sizeof(od));
      memset(vis1,0,sizeof(vis1));
      for (i=0; i<=n; i++)
      {
         father[i]=i;
         rk[i]=0;
         vis[i]=0;
         num[i]=0;
      }

      for (i=0; i<m; i++)
      {
         scanf ("%d%d",&a,&b);
         if (a==b)//排除单源点
         continue;

         od[a]++; od[b]++;

         if (find(a)!=find(b))
         hebing(find(a),find(b));//生成连通图
      }

      for (i=1; i<=n; i++)
      {
         if (od[i]!=0)//改点在图内
         {
            if (od[i]%2!=0)
            {
               num[find(i)]++;//记录每个连通图所有奇数度的个数
               vis[find(i)]=1;//该连通图已经被找过
            }
         }
      }

      for (i=1; i<=n; i++)
      {
         if (od[i]!=0)
         {
            if (!vis[find(i)])//是连通图但是不存在奇数度点
            {
                num[find(i)]++;
                vis[find(i)]=2;
            }
            else
            if (vis[find(i)]==1)//存在奇数度的连通图除 2
            {
               num[find(i)]/=2;
               vis[find(i)]=2;
            }
         }
      }

      for (i=1; i<=n; i++)
      {
         sum+=num[i];
      }
      printf("%d\n",sum);
   }
}

练习



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值