zoukankan      html  css  js  c++  java
  • 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
    ");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 +
    ",ans[i][0]);
                else
                  printf("%d -
    ",ans[i][1]);
            }
        }
        else
          printf("No solution
    ");
    
    }
    


  • 相关阅读:
    Linux下卸载openjdk,安装jdk
    dom4j移除节点不成功
    运费模版源码(.net)
    电子商城系统运费模板设计
    【转】js判断手机访问网页
    nopcommerce之一(结构分析)
    js阻止提交表单(post)
    s1=s1+1与s1+=1的区别
    .net中从GridView中导出数据到excel(详细)
    分布式事务中常见的三种解决方案
  • 原文地址:https://www.cnblogs.com/yezekun/p/3925729.html
Copyright © 2011-2022 走看看