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
    ");
    
    }
    


  • 相关阅读:
    POJ 1015 Jury Compromise【DP】
    POJ 1661 Help Jimmy【DP】
    HDU 1074 Doing Homework【状态压缩DP】
    HDU 1024 Max Sum Plus Plus【DP,最大m子段和】
    占坑补题。。最近占的坑有点多。。。
    Codeforces 659F Polycarp and Hay【BFS】
    Codeforces 659E New Reform【DFS】
    Codeforces 659D Bicycle Race【计算几何】
    廖大python实战项目第四天
    廖大python实战项目第三天
  • 原文地址:https://www.cnblogs.com/yezekun/p/3925729.html
Copyright © 2011-2022 走看看