• 【欧拉回路专题】解题报告


    HDU 1878 欧拉回路

      最简单的欧拉回路了,如果结点的出度入度之和不是2的倍数,那么就不是欧拉回路。注意要判断图是否连通。

    #include <vector>
    #include <list>
    #include <map>
    #include <set>
    #include <queue>
    #include <deque>
    #include <stack>
    #include <algorithm>
    #include <sstream>
    #include <iostream>
    #include <iomanip>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <queue>
    #include <cmath>
    using namespace std;
    #define pii         pair<int,int>
    #define clr(a)      memset((a),0,sizeof (a))
    #define rep(i,a,b)  for(int i=(a);i<=(int)(b);i++)
    #define per(i,a,b)  for(int i=(a);i>=(int)(b);i--)
    #define inf         0x3f3f3f3f
    #define eps         1e-6
    #define MAXN        1<<20
    #define MAXM        100000007
    #define MOD         1000000007
    #define debug       puts("reach here")
    #define MP          make_pair
    #define PB          push_back
    #define RI(x)       scanf("%d",&x)
    #define RII(x,y)    scanf("%d%d",&x,&y)
    #define RIII(x,y,z) scanf("%d%d%d",&x,&y,&z)
    typedef long long LL;
    
    int g[MAXN];
    int n, m;
    int f[MAXN];
    int h[MAXN];
    int r[MAXN];
    vector<int> vs[MAXN];
    
    void init()
    {
        clr(g); clr(h);
        rep(i,0,n)
            f[i] = i, vs[i].clear();
    }
    
    int find(int x)
    {
        return f[x] == x ? x : (f[x] = find(f[x]));
    }
    
    void union_set(int a, int b)
    {
        int x = find(a);
        int y = find(b);
        f[x] = y;
    }
    
    int main()
    {
        int a, b;
        while(RII(n, m) != EOF)
        {
            init();
            rep(i,1,m)
            {
                RII(a, b);
                g[a]++; g[b]++;
                union_set(a, b);
            }
            rep(i,1,n) find(i);
            int k = 0;
            rep(i,1,n)
            {
                if(!h[f[i]])
                {
                    h[f[i]] = ++k;
                    r[k] = f[i];
                    vs[k].PB(i);
                }
                else
                    vs[h[f[i]]].PB(i);
            }
            int cnt = 0;
            rep(i,1,k)
            {
                int tmp = 0;
                int num = vs[i].size();
                rep(j,0,num-1)
                    tmp += g[vs[i][j]]&1;
                
                if(tmp == 0 && num != 1) cnt++;
                else cnt += tmp / 2;
            }
            printf("%d
    ", cnt);
        }
        return 0;
    }
    View Code

    HDU 3018 Ant Trip

      对于本题的图,可能存在多个连通分量,那么对于每个连通分量,如果不存在奇数度的点,那么该分量是构成欧拉回路,只需要一个队伍就能走遍;如果奇数度的点有n个,那么需要n/2个队伍才能走遍,画一下图就很明了了。

    #include <vector>
    #include <list>
    #include <map>
    #include <set>
    #include <queue>
    #include <deque>
    #include <stack>
    #include <algorithm>
    #include <sstream>
    #include <iostream>
    #include <iomanip>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <queue>
    #include <cmath>
    using namespace std;
    #define pii         pair<int,int>
    #define clr(a)      memset((a),0,sizeof (a))
    #define rep(i,a,b)  for(int i=(a);i<=(int)(b);i++)
    #define per(i,a,b)  for(int i=(a);i>=(int)(b);i--)
    #define inf         0x3f3f3f3f
    #define eps         1e-6
    #define MAXN        1<<20
    #define MAXM        100000007
    #define MOD         1000000007
    #define debug       puts("reach here")
    #define MP          make_pair
    #define PB          push_back
    #define RI(x)       scanf("%d",&x)
    #define RII(x,y)    scanf("%d%d",&x,&y)
    #define RIII(x,y,z) scanf("%d%d%d",&x,&y,&z)
    typedef long long LL;
    
    int g[MAXN];
    int n, m;
    int f[MAXN];
    int h[MAXN];
    int r[MAXN];
    vector<int> vs[MAXN];
    
    void init()
    {
        clr(g); clr(h);
        rep(i,0,n)
            f[i] = i, vs[i].clear();
    }
    
    int find(int x)
    {
        return f[x] == x ? x : (f[x] = find(f[x]));
    }
    
    void union_set(int a, int b)
    {
        int x = find(a);
        int y = find(b);
        f[x] = y;
    }
    
    int main()
    {
        int a, b;
        while(RII(n, m) != EOF)
        {
            init();
            rep(i,1,m)
            {
                RII(a, b);
                g[a]++; g[b]++;
                union_set(a, b);
            }
            rep(i,1,n) find(i);
            int k = 0;
            rep(i,1,n)
            {
                if(!h[f[i]])
                {
                    h[f[i]] = ++k;
                    r[k] = f[i];
                    vs[k].PB(i);
                }
                else
                    vs[h[f[i]]].PB(i);
            }
            int cnt = 0;
            rep(i,1,k)
            {
                int tmp = 0;
                int num = vs[i].size();
                rep(j,0,num-1)
                    tmp += g[vs[i][j]]&1;
                
                if(tmp == 0 && num != 1) cnt++;
                else cnt += tmp / 2;
            }
            printf("%d
    ", cnt);
        }
        return 0;
    }
    View Code

    HDU 1116 Play on Words

      对每个单词的首尾字母连边,看是否能构成欧拉通路或者欧拉回路,有两种做法:

      1. 分别判断是否是欧拉通路和欧拉回路。

      2. 如果可以构成欧拉回路,那答案是肯定的;否则设法将欧拉通路变为欧拉回路(找出欧拉通路首尾点,额外添加一条边构成欧拉回路),再计算一次,看是否能构成欧拉回路。

      当然,两种做法都要先判断连通性,谨记欧拉回路是基于连通图的。

      我用的第一种方法。

    #include <vector>
    #include <list>
    #include <map>
    #include <set>
    #include <queue>
    #include <deque>
    #include <stack>
    #include <algorithm>
    #include <sstream>
    #include <iostream>
    #include <iomanip>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <queue>
    #include <cmath>
    using namespace std;
    #define pii         pair<int,int>
    #define clr(a)      memset((a),0,sizeof (a))
    #define    rep(i,a,b)  for(int i=(a);i<=(int)(b);i++)
    #define    per(i,a,b)  for(int i=(a);i>=(int)(b);i--)
    #define    inf         0x3f3f3f3f
    #define    eps         1e-6
    #define    MAXN        1<<20
    #define MAXM        100000007
    #define MOD         1000000007
    #define debug       puts("reach here")
    #define MP          make_pair
    #define PB          push_back
    #define RI(x)       scanf("%d",&x)
    #define RII(x,y)    scanf("%d%d",&x,&y)
    #define RIII(x,y,z) scanf("%d%d%d",&x,&y,&z)
    typedef long long LL;
    
    int n, m, f[MAXN], g[MAXN];
    char s[MAXM];
    bool h[MAXN];
    int v[MAXN]; // 记录出现的字母
    
    int find(int x)
    {
        return f[x] == x ? x : (f[x] = find(f[x]));
    }
    
    void union_set(int u, int v)
    {
        int x = find(u);
        int y = find(v);
        f[x] = y;
    }
    
    int main()
    {
        int t, a, b;
        RI(t);
        while(t--)
        {
            RI(n);
            clr(g); clr(h);
            rep(i,0,26) f[i] = i;
            int k = 0;
            rep(i,1,n)
            {
                scanf("%s", s);
                a = s[0] - 'a';
                b = s[strlen(s)-1] - 'a';
                g[a]++; g[b]--;
                union_set(a, b);
                if(!h[a])
                    v[++k] = a, h[a] = true;
                if(!h[b])
                    v[++k] = b, h[b] = true;
            }
            bool flag = true;
            rep(i,1,k-1)
                if(find(v[i]) != find(v[i+1]))
                    flag = false;
            int cnt1 = 0; // 记录出现度为1的节点的个数,即起点
            int cnt2 = 0; // 记录出现度为-1的节点的个数,即终点
            rep(i,0,25)
            {
                if(abs(g[i]) > 1)
                {
                    flag = false;
                    break;
                }
                if(g[i] == 1)
                    cnt1++;
                if(g[i] == -1)
                    cnt2++;
            }
            if(!flag || cnt1 > 1 || cnt2 > 1)
                printf("The door cannot be opened.
    ");
            else
                printf("Ordering is possible.
    ");  
        }
        return 0;
    }
    View Code

    HDU 2894 DeBruijin

      磁鼓欧拉回路。

      举个具体例子吧,比如k=3的情况,设当前有一个结点为“010”,那么根据欧拉回路一笔画的想法,和该结点相连的结点应该是“100”和“101”,也就是原结点向左移一位然后最低位可以是“0”或“1”,根据这个思路,从“000”开始,先访问下一个低位为0的结点,在访问为1的结点,就能保证所得答案为最小,利用栈保存过程中遇到的可行结点,最后倒序输出栈即可。

    #include <vector>
    #include <list>
    #include <map>
    #include <set>
    #include <queue>
    #include <deque>
    #include <stack>
    #include <algorithm>
    #include <sstream>
    #include <iostream>
    #include <iomanip>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <queue>
    #include <cmath>
    using namespace std;
    #define pii         pair<int,int>
    #define clr(a)      memset((a),0,sizeof (a))
    #define rep(i,a,b)  for(int i=(a);i<=(int)(b);i++)
    #define per(i,a,b)  for(int i=(a);i>=(int)(b);i--)
    #define inf         0x3f3f3f3f
    #define eps         1e-6
    #define MAXN        1<<20
    #define MAXM        100000007
    #define MOD         1000000007
    #define debug       puts("reach here")
    #define MP          make_pair
    #define PB          push_back
    #define RI(x)       scanf("%d",&x)
    #define RII(x,y)    scanf("%d%d",&x,&y)
    #define RIII(x,y,z) scanf("%d%d%d",&x,&y,&z)
    typedef long long LL;
    
    int n;
    bool vis[MAXN];
    int stk[MAXN], top;
    
    void dfs(int u)
    {
        rep(i,0,1)
        {
            int t = ((u<<1)&((1<<n)-1)) + i;
            if(!vis[t])
            {
                vis[t] = true;
                dfs(t);
                stk[top++] = i;
            }
        }
    }
    
    void init()
    {
        clr(vis);
        top = 0;
    }
    
    int main()
    {
        while(RI(n) != EOF)
        {
            init();
            printf("%d ", 1 << n);
            dfs(0);
            rep(i,1,n-1)
                printf("0");
            per(i,top-1,n-1)
                printf("%d", stk[i]);
            putchar('
    ');
        }
        return 0;
    }
    View Code

    HDU 1956 Sightseeing tour

      混合欧拉+最大流。

      对于双向边,任意定向(至于为什么可以这样做,搞清楚求后面求最大流的过程后应该会很清楚了)。双向边用于建图(单向边不用于建图)。

      然后是统计结点的度,计算差值 x = outg[i] - ing[i],如果x>0,源点到 i 连一条边,权值为x/2,也就是说我们需要把与结点 i 相连的x/2条边反向,那么outg[i] == ing[i];同理,如果x<0,连边 i 到汇点,权值为-x/2。最后,如果求出的最大流等于需要反向的总边数,也就是说该流网络满流,说明我们可以成功把想要反向的所有边都反向,那么就能符合题目要求了。

    #include <vector>
    #include <list>
    #include <map>
    #include <set>
    #include <queue>
    #include <deque>
    #include <stack>
    #include <algorithm>
    #include <sstream>
    #include <iostream>
    #include <iomanip>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <queue>
    #include <cmath>
    using namespace std;
    #define pii         pair<int,int>
    #define clr(a)      memset((a),0,sizeof (a))
    #define rep(i,a,b)  for(int i=(a);i<=(int)(b);i++)
    #define per(i,a,b)  for(int i=(a);i>=(int)(b);i--)
    #define inf         0x3f3f3f3f
    #define eps         1e-6
    #define MAXN        1<<20
    #define MAXM        100000007
    #define MOD         1000000007
    #define debug       puts("reach here")
    #define MP          make_pair
    #define PB          push_back
    #define RI(x)       scanf("%d",&x)
    #define RII(x,y)    scanf("%d%d",&x,&y)
    #define RIII(x,y,z) scanf("%d%d%d",&x,&y,&z)
    typedef long long LL;
    struct Edge
    {
        int v, w, next;
    }E[MAXM];
    
    int n, m;
    int head[MAXN], NE;
    
    int ing[MAXN], outg[MAXN]; 
    
    int d[MAXN];  
    bool vis[MAXN];   
    int q[MAXN];     
    
    void add_edge (int u, int v, int w)
    {
        E[NE].v = v;   
        E[NE].w = w;
        E[NE].next = head[u];
        head[u] = NE++;
        
        E[NE].v = u;   
        E[NE].w = 0;
        E[NE].next = head[v];
        head[v] = NE++;
    }
    
    int BFS (int s, int t)
    {
        memset(d, 0x7f, sizeof(d));
        memset(vis, false, sizeof(vis));
    
        int qn = 0 ;
        d[s] = 0 ;
        vis[s] = true ;
        q[qn++] = s ;
    
        for (int qf = 0; qf < qn; ++qf )
        {
            int u = q[qf];
            for (int i = head[u]; i != -1; i = E[i].next)
            {
                int v = E[i].v;
                if (E[i].w > 0 && !vis[v])
                {
                    d[v] = d[u] + 1 ;
                    vis[v] = true ;
                    q[qn++] = v ;
                    if (v == t) return d[t];
                }
            }
        }
        return MAXN;
    }
    
    int DFS (int u, int df, int s, int t)
    {
        if (u == t) return df ;
    
        if (vis[u]) return 0 ;
        vis[u] = true;
    
        for (int i = head[u]; i != -1; i = E[i].next)
        {
            int v = E[i].v ;
            if (E[i].w > 0 && d[u] + 1 == d[v])
            {
                int f = DFS (v, min(df, E[i].w), s , t);
                if ( f )
                {
                    E[i].w -= f ;
                    E[i ^ 1].w += f ;
                    return f ;
                }
            }
        }
        return 0 ;
    }
    
    int dinic (int s, int t)
    {
        int flow = 0 ;
        while (BFS (s, t) < MAXN)
            while ( true )
            {
                clr(vis);
                int f = DFS (s, inf, s, t);
                if( !f ) break;
                flow += f ;
            }
        return flow;
    }
    
    void init()
    {
        clr(ing); clr(outg);
        NE = 0;
        memset(head, -1, sizeof head);
    }
    
    int main()
    {
        int a, b, c, t;
        RI(t);
        while(t--)
        {
            RII(n, m);
            init();
            rep(i,1,m)
            {
                scanf("%d%d%d", &a, &b, &c);
                if(a == b) continue;
                outg[a]++; ing[b] ++;
                if(!c) add_edge(a, b, 1);
            }
            bool flag = true;
            rep(i,1,n)
            {
                int tot = ing[i] + outg[i];
                if(tot & 1) flag = false;
                if(!flag) break;
            }
            if(!flag)
            {
                puts("impossible");
                continue;
            }
            int sum = 0;
            rep(i,1,n)
            {
                int x = outg[i] - ing[i];
                if(x > 0)
                {
                    add_edge(0, i, x/2);
                    sum += x/2;
                }
                if(x < 0)
                    add_edge(i, n+1, -x/2);
            }
            if(dinic(0, n+1) == sum)
                puts("possible");
            else
                puts("impossible");
        }
        return 0;
    }
    View Code

    HDU 3472 HS BDC

      此题和上一题类似,混和欧拉+最大流,不再赘述。、

    #include <vector>
    #include <list>
    #include <map>
    #include <set>
    #include <queue>
    #include <deque>
    #include <stack>
    #include <algorithm>
    #include <sstream>
    #include <iostream>
    #include <iomanip>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <queue>
    #include <cmath>
    using namespace std;
    #define pii         pair<int,int>
    #define clr(a)      memset((a),0,sizeof (a))
    #define rep(i,a,b)  for(int i=(a);i<=(int)(b);i++)
    #define per(i,a,b)  for(int i=(a);i>=(int)(b);i--)
    #define inf         0x3f3f3f3f
    #define eps         1e-6
    #define MAXN        1<<20
    #define MAXM        100000007
    #define MOD         1000000007
    #define debug       puts("reach here")
    #define MP          make_pair
    #define PB          push_back
    #define RI(x)       scanf("%d",&x)
    #define RII(x,y)    scanf("%d%d",&x,&y)
    #define RIII(x,y,z) scanf("%d%d%d",&x,&y,&z)
    typedef long long LL;
    
    struct Edge
    {
        int v, w, next;
    }E[MAXM]; 
    
    int n, m;
    int head[MAXN], NE;
    
    char s[MAXN];
    int ing[MAXN], outg[MAXN]; 
    int f[MAXN];
    vector<int> vs;
    bool h[MAXN];
    
    int d[MAXN];      
    bool vis[MAXN]; 
    int q[MAXN];     
    
    void add_edge (int u, int v, int w)
    {
        E[NE].v = v;   
        E[NE].w = w;
        E[NE].next = head[u];
        head[u] = NE++;
        
        E[NE].v = u;   
        E[NE].w = 0;
        E[NE].next = head[v];
        head[v] = NE++;
    }
    
    int BFS (int s, int t)
    {
        memset(d, 0x7f, sizeof(d));
        memset(vis, false, sizeof(vis));
    
        int qn = 0 ;
        d[s] = 0 ;
        vis[s] = true ;
        q[qn++] = s ;
    
        for (int qf = 0; qf < qn; ++qf )
        {
            int u = q[qf];
            for (int i = head[u]; i != -1; i = E[i].next)
            {
                int v = E[i].v;
                if (E[i].w > 0 && !vis[v])
                {
                    d[v] = d[u] + 1 ;
                    vis[v] = true ;
                    q[qn++] = v ;
                    if (v == t) return d[t];
                }
            }
        }
        return MAXN;
    }
    
    int DFS (int u, int df, int s, int t)
    {
        if (u == t) return df ;
    
        if (vis[u]) return 0 ;
        vis[u] = true;
    
        for (int i = head[u]; i != -1; i = E[i].next)
        {
            int v = E[i].v ;
            if (E[i].w > 0 && d[u] + 1 == d[v])
            {
                int f = DFS (v, min(df, E[i].w), s , t);
                if ( f )
                {
                    E[i].w -= f ;
                    E[i ^ 1].w += f ;
                    return f ;
                }
            }
        }
        return 0 ;
    }
    
    int dinic (int s, int t)
    {
        int flow = 0 ;
        while (BFS (s, t) < MAXN)
            while ( true )
            {
                clr(vis);
                int f = DFS (s, inf, s, t);
                if( !f ) break;
                flow += f ;
            }
        return flow;
    }
    
    int find(int x)
    {
        return f[x] == x ? x : (f[x] = find(f[x]));
    }
    
    void union_set(int u, int v)
    {
        int x = find(u);
        int y = find(v);
        f[x] = y;
    }
    
    void init()
    {
        clr(ing); clr(h);
        clr(outg);
        vs.clear();
        NE = 0;
        memset(head, -1, sizeof head);
        rep(i,0,26) f[i] = i;
    }
    
    int main()
    {
        int t, a, b, c;
        RI(t);
        rep(cas,1,t)
        {
            RI(n);
            init();
            rep(i,1,n)
            {
                scanf("%s%d", s, &c);
                a = s[0] - 'a' + 1;
                b = s[strlen(s) - 1] - 'a' + 1;
                if(!h[a]) vs.PB(a), h[a] = true;
                if(!h[b]) vs.PB(b), h[b] = true;
                if(a == b) continue;
                outg[a]++; ing[b] ++;
                union_set(a, b);
                if(c) add_edge(a, b, 1);
            }
            printf("Case %d: ", cas);
            bool flag = true;
            rep(i,0,vs.size()-2)
            {
                if(find(vs[i]) != find(vs[i+1]))
                    flag = false;
                if(!flag) break;
            }
            if(!flag)
            {
                puts("Poor boy!");
                continue;
            }
            int cnt = 0, a1, a2;
            rep(i,0,vs.size()-1)
            {
                int tot = ing[vs[i]] + outg[vs[i]];
                if(tot & 1)
                {
                    cnt++;
                    if(cnt == 1)
                        a1 = vs[i];
                    if(cnt == 2)
                        a2 = vs[i];
                }
            }
            if(cnt > 2)
            {
                puts("Poor boy!");
                continue;
            }
            if(cnt == 2)
            {
                add_edge(a1, a2, 1);
                outg[a1]++; ing[a2]++;
            } 
            int sum = 0;
            rep(i,0,vs.size()-1)
            {
                int x = outg[vs[i]] - ing[vs[i]];
                if(x > 0)
                {
                    add_edge(0, vs[i], x/2);
                    sum += x/2;
                }
                if(x < 0)
                    add_edge(vs[i], 27, -x/2);
            }
            if(dinic(0, 27) == sum)
                puts("Well done!");
            else
                puts("Poor boy!");
        }
        return 0;
    }
    View Code

    POJ 1041 John's trip

      输出欧拉回路。

      说白了就是一个dfs,代码很简单,不难理解。

    #include <vector>
    #include <list>
    #include <map>
    #include <set>
    #include <queue>
    #include <deque>
    #include <stack>
    #include <algorithm>
    #include <sstream>
    #include <iostream>
    #include <iomanip>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <queue>
    #include <cmath>
    using namespace std;
    #define pii         pair<int,int>
    #define clr(a)      memset((a),0,sizeof (a))
    #define rep(i,a,b)  for(int i=(a);i<=(int)(b);i++)
    #define per(i,a,b)  for(int i=(a);i>=(int)(b);i--)
    #define inf         0x3f3f3f3f
    #define eps         1e-6
    #define MAXN        1<<20
    #define MAXM        100000007
    #define MOD         1000000007
    #define debug       puts("reach here")
    #define MP          make_pair
    #define PB          push_back
    #define RI(x)       scanf("%d",&x)
    #define RII(x,y)    scanf("%d%d",&x,&y)
    #define RIII(x,y,z) scanf("%d%d%d",&x,&y,&z)
    typedef long long LL;
    
    int x, y, z;
    int m[MAXN][MAXM];
    int n, E, s, t;
    int g[MAXM];
    bool vis[MAXM], tag;
    int stk[MAXM];
    int top;
    
    void dfs(int u)
    {
        rep(i,1,E)
        {
            if(m[u][i] && !vis[i])
            {
                vis[i] = true;
                dfs(m[u][i]);
                stk[top++] = i;
            }
        }
    }
    
    void init()
    {
        clr(g); 
        clr(m);
        clr(vis);
        E = -1;
        s = inf;
        t = -1;
        top = 0;
    }
    
    int main()
    {
        while(RII(x, y) != EOF)
        {
            if(x == 0 && y == 0) break;
            RI(z);
            init();
            E = max(E, z);
            s = min(s, min(x, y));
            t = max(t, max(x, y));
            m[x][z] = y;
            m[y][z] = x;
            g[x]++; g[y]++;
            while(RII(x, y) != EOF)
            {
                if(x == 0 && y == 0) break;
                RI(z);
                m[x][z] = y;
                m[y][z] = x;
                E = max(E, z);
                s = min(s, min(x, y));
                t = max(t, max(x, y));
                g[x]++; g[y]++;
            }
            bool flag = false;
            rep(i,1,t)
            {
                flag = g[i] & 1;
                if(flag) break;
            }
            if(flag)
            {
                puts("Round trip does not exist.");
                continue;
            }
            dfs(s);
            per(i,top-1,0)
                printf("%d%c", stk[i], i == 0 ? '
    ' : ' ');
        }
        return 0;
    }
    View Code

    POJ 2230 Watchcow

      还是输出欧拉回路,不过和POJ 1041有一点儿不同就是输出的是点,代码稍微有一点儿不同,需仔细体会。

    #include <vector>
    #include <list>
    #include <map>
    #include <set>
    #include <queue>
    #include <deque>
    #include <stack>
    #include <algorithm>
    #include <sstream>
    #include <iostream>
    #include <iomanip>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <queue>
    #include <cmath>
    using namespace std;
    #define pii         pair<int,int>
    #define clr(a)      memset((a),0,sizeof (a))
    #define rep(i,a,b)  for(int i=(a);i<=(int)(b);i++)
    #define per(i,a,b)  for(int i=(a);i>=(int)(b);i--)
    #define inf         0x3f3f3f3f
    #define eps         1e-6
    #define MAXN        1<<20
    #define MAXM        100000007
    #define MOD         1000000007
    #define debug       puts("reach here")
    #define MP          make_pair
    #define PB          push_back
    #define RI(x)       scanf("%d",&x)
    #define RII(x,y)    scanf("%d%d",&x,&y)
    #define RIII(x,y,z) scanf("%d%d%d",&x,&y,&z)
    typedef long long LL;
    struct Node
    {
        int v, next;
    }E[MAXM];
    
    int n, m;
    int NE, head[MAXN];
    bool vis[MAXM];
    
    void add_edge(int u, int v)
    {
        E[NE].v = v;
        E[NE].next = head[u];
        head[u] = NE++;
    }
    
    void dfs(int u)
    {
        for(int i = head[u]; i != -1; i = E[i].next)
        {
            int v = E[i].v;
            if(!vis[i])
            {
                vis[i] = true;
                dfs(v);
            }
        }
        printf("%d
    ", u);
    }
    
    void init()
    {
        NE = 0; clr(vis);
        memset(head, -1, sizeof head);
    }
    
    int main()
    {
        int a, b;
        RII(n, m);
        init();
        rep(i,1,m)
        {
            RII(a, b);
            add_edge(a, b);
            add_edge(b, a);
        }
        dfs(1);
        return 0;
    }
    View Code

    POJ 2513 Colored Sticks

      字典树+欧拉路径。

      一开始用map存单词,爆了内存。后来才想起用字典树来标记单词,然后判断一下能否构成欧拉回路或欧拉通路即可。(以下代码采用泽阳师兄的字典树写法,比我原来的指针型动态分配内存写法快了一个数量级,此字典树写法才是标准的)。

    #include <vector>
    #include <list>
    #include <map>
    #include <set>
    #include <queue>
    #include <deque>
    #include <stack>
    #include <algorithm>
    #include <sstream>
    #include <iostream>
    #include <iomanip>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <queue>
    #include <cmath>
    using namespace std;
    #define pii         pair<int,int>
    #define clr(a)      memset((a),0,sizeof (a))
    #define rep(i,a,b)  for(int i=(a);i<=(int)(b);i++)
    #define per(i,a,b)  for(int i=(a);i>=(int)(b);i--)
    #define inf         0x3f3f3f3f
    #define eps         1e-6
    #define MAXN        1<<20
    #define MAXM        100000007
    #define MOD         1000000007
    #define debug       puts("reach here")
    #define MP          make_pair
    #define PB          push_back
    #define RI(x)       scanf("%d",&x)
    #define RII(x,y)    scanf("%d%d",&x,&y)
    #define RIII(x,y,z) scanf("%d%d%d",&x,&y,&z)
    typedef long long LL;
    int g[MAXN];
    int n, m, k;
    int f[MAXN];
    
    struct Tree
    {
        int v;
        int next[26];
    }P[1000005], root;
    
    int find(int x)
    {
        return f[x] == x ? x : (f[x] = find(f[x]));
    }
    
    void union_set(int u, int v)
    {
        int x = find(u);
        int y = find(v);
        f[x] = y;
    }
    
    int trie(char *s)
    {
        int h = 0;
        for(int i = 0; s[i]; i++)
        {
            int a = s[i] - 'a';
            if(!P[h].next[a])
                P[h].next[a] = ++k;
            h = P[h].next[a];
            
        }
        if(P[h].v == 0)
            P[h].v = ++n;
        return P[h].v;
    }
    
    int main()
    {
        int a, b;
        char u[12], v[12];
        clr(g);
        n = 0; k = 0;
        rep(i,0,MAXN) f[i] = i;
        while(scanf("%s%s", u, v) != EOF)
        {
            a = trie(u); b = trie(v);
            if(a == b) continue;
            g[a]++; g[b]++;
            union_set(a, b);
        }
        bool flag = true;
        rep(i,1,n-1)
        {
            if(find(i) != find(i+1))
            {
                flag = false;
                break;
            }
        }
        if(!flag)
        {
            puts("Impossible");
            return 0;
        }
        int cnt = 0;
        rep(i,1,n)
            cnt += g[i] & 1;
        if(cnt > 2)
            puts("Impossible");
        else
            puts("Possible");
        
        return 0;
    }
    View Code

    POJ 2337 Catenyms

      因为要保证字典序最小,所以要先从大到小排一下序(没写错,是从大到小,因为到深搜递归的时候越小的字符串保存离栈顶越近),然后依然是打印出欧拉回路。

    #include <vector>
    #include <list>
    #include <map>
    #include <set>
    #include <queue>
    #include <deque>
    #include <stack>
    #include <algorithm>
    #include <sstream>
    #include <iostream>
    #include <iomanip>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <queue>
    #include <cmath>
    using namespace std;
    #define pii         pair<int,int>
    #define clr(a)      memset((a),0,sizeof (a))
    #define rep(i,a,b)  for(int i=(a);i<=(int)(b);i++)
    #define per(i,a,b)  for(int i=(a);i>=(int)(b);i--)
    #define inf         0x3f3f3f3f
    #define eps         1e-6
    #define MAXN        1<<20
    #define MAXM        100000007
    #define MOD         1000000007
    #define debug       puts("reach here")
    #define MP          make_pair
    #define PB          push_back
    #define RI(x)       scanf("%d",&x)
    #define RII(x,y)    scanf("%d%d",&x,&y)
    #define RIII(x,y,z) scanf("%d%d%d",&x,&y,&z)
    typedef long long LL;
    
    struct Edge
    {
        int v, next;
    }E[MAXM]; 
    
    int n, m;
    int head[MAXN], NE;
    
    string s[MAXM];
    int ing[MAXN], outg[MAXN]; 
    int f[MAXN];
    vector<int> vs;
    int h[MAXM];
    int stk[MAXM], top;
    bool vis[MAXM];
    
    void add_edge (int u, int v)
    {
        E[NE].v = v;   
        E[NE].next = head[u];
        head[u] = NE++;
    }
    
    int find(int x)
    {
        return f[x] == x ? x : (f[x] = find(f[x]));
    }
    
    void union_set(int u, int v)
    {
        int x = find(u);
        int y = find(v);
        f[x] = y;
    }
    
    void init()
    {
        clr(h);
        clr(ing); 
        clr(vis);
        clr(outg);
        vs.clear();
        NE = 1;
        top = 0;
        memset(head, -1, sizeof head);
        rep(i,0,26) f[i] = i;
    }
    
    void dfs(int u, int d)
    {
        for(int i = head[u]; i != -1; i = E[i].next)
        {
            int v = E[i].v;
            if(!vis[i])
            {
                vis[i] = true;
                dfs(v, i);
            }
        }
        if(d != -1)
            stk[top++] = d;
    }
    
    bool cmp(string u, string v)
    {
        return u >= v;
    }
    
    int check()
    {
        int num=0,cnt1=0,cnt2=0,id=-1;
        rep(j,0,vs.size()-1)
        {
            int i = vs[j];
            if(find(i) == i)
                num++;
            if(ing[i]!=outg[i])
            {
                if(ing[i]-outg[i]==1)
                    cnt1++;
                else if(outg[i]-ing[i]==1)
                {
                    cnt2++;
                    id=i;
                }
                else 
                    return -1;
            }
        }
        if(num!=1)
            return -1;
           if(!((cnt1==1&&cnt2==1)||(cnt1==0&&cnt2==0)))
               return -1;
        if(id==-1)
        {
            for(int i=0;i<26;i++)
            {
                if(outg[i]>0)
                {
                    id=i;
                    break;
                }
            }
        }
        return id;
    }
    
    int main()
    {
        int t, a, b;
        cin >> t;
        while(t--)
        {
            RI(n);
            init();
            rep(i,1,n)
                cin >> s[i];
            sort(s + 1, s + 1 + n, cmp);
            rep(i,1,n)    
            {
                a = s[i][0] - 'a' + 1;
                b = s[i][s[i].length() - 1] - 'a' + 1;
                if(!h[a]) vs.PB(a), h[a] = true;
                if(!h[b]) vs.PB(b), h[b] = true;
                outg[a]++; ing[b]++;
                union_set(a, b);
                add_edge(a, b);
            }
            int st = check();
            if(st == -1)
            {
                cout << "***" << endl;
                continue;
            }
            dfs(st, -1);
            per(i,top-1,0)
            {
                cout << s[stk[i]];
                if(i != 0) cout << '.';
            }
            cout << endl;
        }
        return 0;
    }
    View Code

    POJ 1392 Ouroboros Snake

      磁鼓欧拉回路,和前面HDU 2894类似。

    #include <vector>
    #include <list>
    #include <map>
    #include <set>
    #include <queue>
    #include <deque>
    #include <stack>
    #include <algorithm>
    #include <sstream>
    #include <iostream>
    #include <iomanip>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <queue>
    #include <cmath>
    using namespace std;
    #define pii         pair<int,int>
    #define clr(a)      memset((a),0,sizeof (a))
    #define rep(i,a,b)  for(int i=(a);i<=(int)(b);i++)
    #define per(i,a,b)  for(int i=(a);i>=(int)(b);i--)
    #define inf         0x3f3f3f3f
    #define eps         1e-6
    #define MAXN        1<<20
    #define MAXM        100000007
    #define MOD         1000000007
    #define debug       puts("reach here")
    #define MP          make_pair
    #define PB          push_back
    #define RI(x)       scanf("%d",&x)
    #define RII(x,y)    scanf("%d%d",&x,&y)
    #define RIII(x,y,z) scanf("%d%d%d",&x,&y,&z)
    typedef long long LL;
    
    int n, k, cnt;
    bool vis[MAXN];
    int stk[MAXN], top;
    int ans[MAXN];
    
    void dfs(int u)
    {
        rep(i,0,1)
        {
            int t = ((u<<1)&((1<<n)-1)) + i;
            if(!vis[t])
            {
                vis[t] = true;
                dfs(t);
                stk[top++] = i;
            }
        }
    }
    
    void init()
    {
        clr(vis);
        top = 0;
        cnt = 0;
    }
    
    int main()
    {
        while(RII(n, k) != EOF)
        {
            if(n == 0 && k == 0) break;
            init();
            dfs(0);
            rep(i,1,n-1)
                ans[cnt++] = 0;
            per(i,top-1,0)
                ans[cnt++] = stk[i];
            int sum = 0;
            rep(i,k,k+n-1)
                sum = (sum<<1) | ans[i];
            printf("%d
    ", sum);
        }
        return 0;
    }
    View Code

    POJ 1780 Code

      这道题很蛋痛啊,要写非递归的磁鼓欧拉回路,不然要RE的。

    #include <vector>
    #include <list>
    #include <map>
    #include <set>
    #include <queue>
    #include <deque>
    #include <stack>
    #include <algorithm>
    #include <sstream>
    #include <iostream>
    #include <iomanip>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <queue>
    #include <cmath>
    using namespace std;
    //#pragma comment(linker, "/STACK:102400000,102400000")
    #define pii         pair<int,int>
    #define clr(a)      memset((a),0,sizeof (a))
    #define rep(i,a,b)  for(int i=(a);i<=(int)(b);i++)
    #define per(i,a,b)  for(int i=(a);i>=(int)(b);i--)
    #define inf         0x3f3f3f3f
    #define eps         1e-6
    #define MAXN        10000007
    #define MAXM        100000007
    #define MOD         1000000007
    #define debug       puts("reach here")
    #define MP          make_pair
    #define PB          push_back
    #define RI(x)       scanf("%d",&x)
    #define RII(x,y)    scanf("%d%d",&x,&y)
    #define RIII(x,y,z) scanf("%d%d%d",&x,&y,&z)
    typedef long long LL;
    
    int n, k, cnt, p;
    int stk[MAXN], top;
    int ans[MAXN];
    int num[MAXN];
    
    void solve()
    {
        stk[top++] = 0;
        num[0]++;
        while(top)
        {
            int u = stk[--top];
            ans[cnt++] = u % 10;
            u /= 10;
            while(num[u] < 10)
            {
                int w = u * 10 + num[u];
                num[u]++;
                stk[top++] = w;
                u = w % p;
            }
        }
    }
    
    void init()
    {
        top = 0;
        cnt = 0;
        p = 1;
        rep(i,1,n-1) p *= 10;
        clr(num);
    }
    
    int main()
    {
        while(RI(n) != EOF)
        {
            if(n == 0) break;
            if(n == 1) {puts("0123456789"); continue;}
            init();
            solve();
            rep(i,1,n) printf("0");
            per(i,cnt-1,n-1)
                printf("%d", ans[i]);
            rep(i,1,n-2) printf("0");
            putchar('
    ');
        }
        return 0;
    }
    View Code
  • 相关阅读:
    许多其他C++的class样本
    cocos2d-x 3.2 它 2048 —— 第三
    hdu 4035 可能性DP 成都网络游戏
    OpenWrt 主的发展版本号trunk MT7620N 无线驱动程序bug
    [leetcode]Permutation Sequence
    Java Swing编程接口(30)---列表框:JList
    [创新工场]2014创新工场校园招聘回文字符串维修
    FFmpeg来源简单分析:结构会员管理系统-AVClass
    [Angular 2] Component relative paths
    [TypeScript] Reflection and Decorator Metadata
  • 原文地址:https://www.cnblogs.com/huangfeihome/p/3302158.html
Copyright © 2020-2023  润新知