• 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("");
            }
        }
    }
  • 相关阅读:
    团队建设
    风云变幻六十年 平板电脑演变史回顾
    在线ide汇总
    XAMPP中启动tomcat报错的解决方法
    ExtJs 中 xtype 与组件类的对应表
    FineReport关于Linux下字体乱码终极解决方案
    SqlDataReader的关闭问题
    MemberShip学习之:注册用户
    索引超出范围。必须为非负值并小于集合大小。
    利用SiteMapPath控件做论坛导航(也适合其它系统)
  • 原文地址:https://www.cnblogs.com/Jadon97/p/8540184.html
Copyright © 2020-2023  润新知