• Poj 2337 Catenyms(有向图DFS求欧拉通路)


    题意:

    给定n个单词, 问是否存在一条欧拉通路(如acm,matal,lack), 如果存在, 输出字典序最小的一条。

    分析:

    这题可以看作http://www.cnblogs.com/Jadon97/p/7210278.html升级版本(那题只问是否存在, 这题需要输出路径)

    判断有向图的欧拉通路, 主要用到出入度的判定和连通性。

    有向图欧拉通路判定方法:图连通;除2个端点外其余节点入度=出度;1个端点入度比出度大1;一个端点入度比出度小1 或 所有节点入度等于出度

    DFS求解算法:选择一个正确的起点,用DFS算法遍历所有的边(每条边只遍历一次),遇到走不通就回退。在搜索前进方向上将遍历过的边按顺序记录下来,这组边的排列就组成了一条欧拉通路或者回

    #include<cstdio>
    #include<iostream>
    #include<vector>
    #include<string>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    string word[2010];
    struct node
    {
        int to,  index;
        node(int _to, int _index): to(_to), index(_index) {};
    };
    vector<node> G[30];
    int degree[30], vis[2010], used[26], ans[2010];
    int n, tot;
    int st;
    int id(int a)
    {
        return a - 'a';
    }
    void dfs(int u)
    {
    //    cout << word[index] << "
    ";
        for(int i = 0; i < G[u].size(); i++)
        {
            int v = G[u][i].to, index = G[u][i].index;
            if(!vis[index])
            {
                vis[index] = 1;
                dfs(v);
                ans[tot++] = index;
            }
        }
    }
    bool judge()
    {
        int cc1 = 0, cc2 = 0; //cc1 出度>入度 cc2 入度>出度
        for(int i = 0; i < 26; i++)
        {
            if(used[i])
            {
                if(degree[i] != 0)
                {
                    if(degree[i] == 1)
                    {
                        cc1++, st = i;//如果出度大于入度, 那么以该点为起点
                    }
                    else if(degree[i] == -1)
                    {
                        cc2++;
                    }
                    else
                    {
                        return false;
                    }
                }
            }
        }
        if((cc1 || cc2) && cc1 + cc2 != 2) //有出度入度不等的点, 而且不止2个
        {
            return false;
        }
        return true;
    }
    int main()
    {
    //    freopen("1.txt","r", stdin);
        int T;
        cin >> T;
        while(T--)
        {
            for(int i = 0; i < 30; i++)
                G[i].clear();
            memset(used, 0, sizeof(used));
            memset(vis, 0, sizeof(vis));
            memset(degree, 0, sizeof(degree));
            tot = 0;
    
            cin >> n;
            for(int i = 0; i < n; i++)
            {
                cin >> word[i];
            }
    
            sort(word, word + n);
            st = 100;
            for(int i = 0; i < n; i++)
            {
                int u = id(word[i][0]), v = id(word[i][word[i].size()-1]);
                G[u].push_back(node(v,i));
                if(u < st)
                    st = u; //从字典序最小的开始遍历
                used[u] = used[v] = 1; //记录u,v是用过的
                degree[u]++, degree[v]--; //出度++, 入度--
            }
    
    
    
            if(!judge())
            {
                printf("***
    ");
                continue;
            }
            dfs(st);
            if(tot != n) //不连通
            {
                printf("***
    ");
                continue;
            }
    
            else
            {
                cout <<  word[ans[tot-1]];
                for(int i = tot - 2; i >= 0; i--)//反向输出路径
                {
                    cout <<"." << word[ans[i]] ;
                }
                puts("");
            }
        }
    }
  • 相关阅读:
    CF1290E Cartesian Tree
    【LeetCode】11. 盛最多水的容器
    【LeetCode】10. 正则表达式匹配
    【LeetCode】9. 回文数
    【LeetCode】8. 字符串转换整数 (atoi)
    【LeetCode】7. 整数反转
    【LeetCode】6. Z 字形变换
    【LeetCode】5. 最长回文子串
    【LeetCode】4. 寻找两个正序数组的中位数[待补充]
    【LeetCode】3. 无重复字符的最长子串
  • 原文地址:https://www.cnblogs.com/Jadon97/p/8540184.html
Copyright © 2020-2023  润新知