• HDU 2894(欧拉回路)


    这个题暴搜10分钟写出来了,也AC了。但听XLK和LYD神牛讲的欧拉回路的方法,真心跪了!

    XLK题解(有改动):

    很显然,第一问的答案就是2^n

    第二问,构造一个有2^(n-1)个节点的图,对应2^(n-1)n-1位二进制数。从代表数k的节点(0<=k<2^(n-1))向代表数(k<<1)&(1<<n-1)的节点,和代表数(k<<1)&(1<<n-1)+1的节点分别连一条边。可以发现这样的图中,所有点的入度和出度都是2,因此这是一个欧拉图。因此我们从0号点开始dfs寻找一个欧拉回路,回溯的时候记录到栈中,最后倒序输出即可。因为要求字典序最小,dfs的时候要注意搜索顺序,先走0边,再走1边。这个算法寻找欧拉回路,每个点、每条边只访问一次,是O(V+E)级别的。

    时间复杂度O(2^n),预计得分100分。

     

    暴搜代码:

     

    View Code
     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <iostream>
     4 #include <cstring>
     5 using namespace std;
     6 bool fg,d[1<<15],vis[1<<15];
     7 int tot,k;
     8 void read()
     9 {
    10     memset(vis,0,sizeof vis);
    11     fg=false;
    12     tot=1<<k;
    13 }
    14 bool check()
    15 {
    16     int i=1,j=tot+1;
    17     for(;i<=k-1;i++,j++)
    18     {
    19         if(d[i]!=d[j]) return false;
    20     }
    21     fg=true;
    22     for(i=1;i<=tot;i++) printf("%d",d[i]);
    23 }
    24 void dfs(int step,int num)
    25 {
    26     if(fg) return;
    27     if(step==tot)
    28     {
    29         check();
    30         return;
    31     }
    32     for(int i=0;i<tot;i++)
    33     {
    34         if(!vis[i])
    35         {
    36             int sk;
    37             if((num>>(k-1))==1) sk=num-(1<<(k-1));
    38             else sk=num;
    39             if(sk==(i>>1))
    40             {
    41                 d[step+k]=i&1;
    42                 vis[i]=true;
    43                 dfs(step+1,i);
    44                 vis[i]=false;
    45             }
    46         }
    47     }
    48 }
    49 void go()
    50 {
    51     printf("%d ",tot);
    52     for(int i=1;i<=k;i++) d[i]=0;
    53     vis[0]=true;
    54     dfs(1,0);
    55     printf("\n");
    56 }
    57 int main()
    58 {
    59     while(scanf("%d",&k)!=EOF)
    60     {
    61         read();
    62         go();
    63     }
    64     return 0;
    65 }

     

    欧拉回路代码:

    View Code
     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cstring>
     4 using namespace std;
     5 int p,d[1<<15],n;
     6 bool vis[1<<15];
     7 void prev()
     8 {
     9     memset(vis,0,sizeof vis);
    10     p=0;
    11 }
    12 void dfs(int u)
    13 {
    14     int to1=(u<<1)&((1<<n)-1);
    15     int to2=to1+1;
    16     if(!vis[to1])
    17     {
    18         vis[to1]=true;
    19         dfs(to1);
    20         d[++p]=0;
    21     }
    22     if(!vis[to2])
    23     {
    24         vis[to2]=true;
    25         dfs(to2);
    26         d[++p]=1;
    27     }
    28 }
    29 void go()
    30 {
    31     dfs(0);
    32     printf("%d ",1<<n);
    33     for(int i=1;i<n;i++) printf("0");
    34     for(int i=p;i>=n;i--) printf("%d",d[i]);
    35     printf("\n");
    36 }
    37 int main()
    38 {
    39     while(scanf("%d",&n)!=EOF)
    40     {
    41         prev();
    42         go();
    43     }
    44     return 0;
    45 }

    后记:

    由于紧张备战NOIP考试,所以,难题和新算法就都暂时不学了,把基础巩固好,发现基础太弱了,难题也不会。。

     

    没有人能阻止我前进的步伐,除了我自己!
  • 相关阅读:
    2020-2021-1 20209315《Linux内核原理与分析》第九周作业
    2020-2021-1 20209315《Linux内核原理与分析》第八周作业
    2020-2021-1 20209315《Linux内核原理与分析》第七周作业
    2020-2021-1 20209315《Linux内核原理与分析》第六周作业
    2020-2021-1 20209315《Linux内核原理与分析》第五周作业
    2020-2021-1 20209315《Linux内核原理与分析》第四周作业
    2020-2021-1 20209315《Linux内核原理与分析》第三周作业
    2020-2021-1 20209315《Linux内核原理与分析》第二周作业
    2020-2021-1 20209310《Linux内核原理与分析》第十一周作业
    2020-2021-1 20209310《Linux内核原理与分析》第九周作业
  • 原文地址:https://www.cnblogs.com/proverbs/p/2649984.html
Copyright © 2020-2023  润新知