SGU101 求有重边的无向图欧拉迹

题意:好多木棒,俩端有数字(0--6)标记,按数字相同的端首尾相连成一条直线(木棒可以相同)。即求有重边的无向图欧拉迹。

先判定是否为欧拉图,俩个条件,不说了。如果是欧拉图,输出路经。

方法:dfs遍历边,回溯时候记录边,遍历过了就标记“双向边”.

那么所记录的恰好是一条逆欧拉迹。不可以前进的时候标记,原因:有可能一笔画失败,导致边不连续,
而回溯的时候记录,原因较复杂,大致证明如下:
分几种情况讨论即可:
1,只有偶数结点。任选一个点,必然从一条出发回到该点,直到无边为止,回溯时边自然连续。

2,有2个奇数结点。当回到某个点时无论圈有没走,必然也连续,见图:



#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n;int nume=0;
int e[205][2];int head[10];
void adde(int f,int l)
{
    e[nume][0]=l;e[nume][1]=head[f];head[f]=nume++;
    e[nume][0]=f;e[nume][1]=head[l];head[l]=nume++;
}
int degree[8];  //度数
int vis[205];   //标记访问
void dfs1(int u)   //判断连通
{ 
    for(int i=head[u];i!=-1;i=e[i][1])
    {
        int v=e[i][0];
        if(!vis[v])
        {
            vis[v]=1;
            dfs1(v);
        }
    }
}
int ans[205][2];int ansnum=0;
void dfs2(int u)             //求欧拉迹
{
    for(int i=head[u];i!=-1;i=e[i][1])
    {
        if(!vis[i])
        {
            vis[i]=1;          //此处同时标记双向边!!!。
            vis[i^1]=1;
            int v=e[i][0];
             dfs2(v);              //回溯的时候记录边,恰是一条欧拉路。
             if(i%2==0)
               ans[ansnum++][0]=i/2+1;
            else
               ans[ansnum++][1]=i/2+1;

        }
    }
}
int main()
{
    scanf("%d",&n);
    for(int i=0;i<8;i++)
        head[i]=-1;
    int tf,tl;
    int tbegin=0;
    for(int i=0;i<n;i++)     
    {
        scanf("%d%d",&tf,&tl);
        tbegin=tf;
        degree[tf]++;degree[tl]++;
        adde(tf,tl);
    }
    int count=0;
    int jis=0;;
    for(int i=0;i<=6;i++)  //度数判定
    {
        if(degree[i]%2)
          {
              count++;
              jis=i;
          }
    }
    if(count==0||count==2)
    {
        int mark=1;
        vis[tbegin]=1;
        dfs1(tbegin);        
        for(int i=0;i<=6;i++)      //连通性判定
          if(vis[i]==0&°ree[i]>0)
              mark=0;
        if(mark==0){ printf("No solution\n");return 0;}
        for(int i=0;i<205;i++)
              vis[i]=0;
        if(count==0)        
          dfs2(tbegin);
        else
          dfs2(jis);
        for(int i=ansnum-1;i>=0;i--)     //逆序输出
        {
            if(ans[i][0]!=0)
              printf("%d +\n",ans[i][0]);
            else
              printf("%d -\n",ans[i][1]);
        }
    }
    else
      printf("No solution\n");

}


posted @ 2014-03-30 22:26  天羽屠龙舞  阅读(280)  评论(0编辑  收藏  举报