有向图的欧拉回路及欧拉道路

来源:互联网 发布:php程序什么梗 编辑:程序博客网 时间:2024/04/29 20:54


 欧拉回路

//有向图

//欧拉回路:1.图连通2.每个点的入度等于出度

//欧拉道路:1.图连通2.每个点的入度等于出度或有两个点入度不等于出度,且一个点出度比入度大一(起点),另一个点入度比出度小一(终点)如下图只能从中间一点开始到中间另一点结束,并且起点出度比入度大一


//程序本身并不复杂,无非是将无向图中对于度数的判断奇偶改为判断入度和出度是否相等
//保存路径时需要注意一点,ans数组是保存的两点,而不是一点是否被访问过(这与图的遍历不同,我一开始就错这),因为欧拉回路是可能重复经过某一点的
#include <cstdio>#include <iostream>#include <queue>using namespace std; int n; int a[101][101]; int indegree[101]; int outdegree[101]; int bfs(); int ans[101][101]; int compare(); void print(int i); int main() {     int m,i,j,c,d;     scanf("%d%d",&n,&m);     for (i=1;i<=m;i++)     {         scanf("%d%d",&c,&d);         a[c][d]=1;         outdegree[c]++;//c的出度加一         indegree[d]++;//d的入度加一     }     if (!bfs())//如果图本身不连通        printf("No\n");        else         if (compare())//如果入度等于出度         {            printf("Yes\n");            printf("路径为:\n");            print(1);         }         else        printf("No\n");     return 0; } int bfs() {     queue<int>q;     int i;     int vis[101],temp;//标记是否访问过     for (i=1;i<=n;i++)        vis[i]=0;     q.push(1);     vis[1]=1;     while(!q.empty())     {         temp=q.front();         q.pop();         for (i=1;i<=n;i++)          if ((a[temp][i])&&(!vis[i]))         {             vis[i]=1;             q.push(i);         }     }     for (i=1;i<=n;i++)        if (!vis[i])        {           printf("%d\n",i);           return 0;        }         return 1;}int compare(){     int i;    for (i=1;i<=n;i++)        if (indegree[i]!=outdegree[i])        return 0;        return 1;}void print(int i){    int v;    for (v=1;v<=n;v++)    if ((a[i][v])&&(!ans[i][v]))    {        ans[i][v]=1;        printf("%d->%d\n",i,v);        print(v);   //递归搜索路径    }}




   欧拉道路


//有向图的欧拉道路的查找即路径打印方式与欧拉通路差不多,关键在于包含欧拉回路的情况下再考虑入度和出度相差1的情况
//有向图的欧拉道路起点必须是出度比入度大一的那个点,所以要先扫描一遍找出那两个点,如果都相等,那就参照欧拉回路的方式做,否则从该点开始路径递归

#include <cstdio>#include <iostream>#include <queue>#include <cmath>using namespace std; int n; int a[101][101]; int indegree[101]; int outdegree[101]; int bfs(); int x[3]; int ans[101][101]; int compare(); void print(int i); int main() {     int m,i,j,c,d;     scanf("%d%d",&n,&m);     x[1]=0;     for (i=1;i<=m;i++)     {         scanf("%d%d",&c,&d);         a[c][d]=1;         outdegree[c]++;//c的出度加一         indegree[d]++;//d的入度加一     }     if (!bfs())//如果图本身不连通        printf("No\n");        else       if (compare())//如果入度等于出度         {            printf("Yes\n");            printf("路径为:\n");            if (!x[1])//如果是欧拉回路,那么哪一点开始都无所谓                print(1);            else            if (outdegree[x[1]]>outdegree[x[2]])//如果a[1]的出度大,那他就是起点            print(x[1]);            else                print(x[2]);         }         else        printf("No\n");     return 0; } int bfs() {     queue<int>q;     int i;     int vis[101],temp;//标记是否访问过     for (i=1;i<=n;i++)        vis[i]=0;     q.push(1);     vis[1]=1;     while(!q.empty())     {         temp=q.front();         q.pop();         for (i=1;i<=n;i++)            if ((a[temp][i])&&(!vis[i]))         {             vis[i]=1;             q.push(i);         }     }     for (i=1;i<=n;i++)        if (!vis[i])        {           printf("%d\n",i);           return 0;        }         return 1;}int compare(){    int i,ok;    ok=0;    for (i=1;i<=n;i++)        if (indegree[i]!=outdegree[i])        {            ok++;            if (ok>2)return 0;//如果入度出度不相等的节点数大于2,那肯定不是欧拉道路            else            x[ok]=i;        }        if (!ok)//如果入度都等于出度,那么是欧拉回路,自然是欧拉通路        return 1;        if (fabs(indegree[x[1]]-indegree[x[2]])!=1)//如果入度相差不是1,那也不是欧拉回路           return 0;}void print(int i){    int v;    for (v=1;v<=n;v++)    if ((a[i][v])&&(!ans[i][v]))    {        ans[i][v]=1;        printf("%d->%d\n",i,v);        print(v);   //递归搜索路径    }}



0 0