poj 2337 Catenyms

点击打开链接poj2377

思路: 并查集+排序+欧拉道路
分析:
1 题目要求的是,是否可以组成欧拉道路并且输出字典序最小的方案
2 和别的题目不一样的是这一题的输出是最小的字典序,所以这里面是一个难点,那么我们应该怎么做呢?其实我们只要对输入的n个单词进行从小到达排序即可
3 然后我们先去判断该有向图是否是单连通的
4 我们去判断是否最多只有两个点的入度不等与出度,其余所有点的出度等于入度
5 如果都满足的话,进行dfs。那么这里面就要注意了,由于要输出路径所以我们必须要这些满足的边(对应单词)压到栈里面,那么这里面就会涉及到字典序最小的问题
6 里面涉及到递归的深刻理解,所以应该要熟练递归的应用

代码:

#include<stack>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

const int N = 30;
int n;
int father[N] , inDegree[N] , outDegree[N];
char words[1010][N];
bool vis[1010];
stack<string>st;
vector<int>v[N];

//排序函数
int cmp(const void *s1 , const void *s2){
    return strcmp((char *)s1 , (char *)s2);
}

void init(){
    memset(vis , false , sizeof(vis));
    memset(inDegree , 0 , sizeof(inDegree));
    memset(outDegree , 0 , sizeof(outDegree));
    for(int i = 0 ; i < N ; i++){
        father[i] = i;
        v[i].clear();
    }
}

int find(int x){
    if(x != father[x])
       father[x] = find(father[x]);
    return father[x];
}

//压栈
void push(int x , int y){
    //这里应该要注意的是由于栈是先入后出所以必须先把字典序大的压入
    for(int i = n-1 ; i >= 0 ; i--){
       if(!vis[i] && words[i][0]-'a' == x){
          if(y == words[i][strlen(words[i])-1]-'a'){
             st.push(words[i]);
             vis[i] = true;
             return;
          }
       }
    }
}

//计算欧道路
void dfs(int cur){
    while(!v[cur].empty()){
         int tmp = *(v[cur].begin());
         v[cur].erase(v[cur].begin());
         dfs(tmp);
         push(cur , tmp);
    }
}

//输出
void output(){
    while(!st.empty()){
        cout<<st.top();
        st.pop();
        if(!st.empty())
           printf(".");
    }
    printf("\n");
}

void solve(){
    int root;
    for(int i = 0 ; i < N ; i++){
       if(vis[i]){
          root = find(i);
          break;
       }
    }
    for(int i = 0 ; i < N ; i++){
       if(vis[i] && root != find(i)){
          puts("***");
          return;
       }
    }
    int cnt = 0;
    for(int i = 0 ; i < N ; i++){
        if(abs(inDegree[i]-outDegree[i]) > 1){
           puts("***");
           return;
        }
        if(abs(inDegree[i]-outDegree[i]) == 1)
            cnt++;
    }
    if(cnt > 2)
        puts("***");
    else{
        int start;
        for(int i = 0 ; i < N ; i++){
            if(outDegree[i]-inDegree[i] == 1){
               start = i;
               break;
            }
        }
        if(!cnt)
           start = words[0][0]-'a';
        memset(vis , false , sizeof(vis));
        dfs(start);
        output();
    }
}

int main(){
    int Case;
    scanf("%d" , &Case);
    while(Case--){
        scanf("%d" , &n);
        init();
        for(int i = 0 ; i < n ; i++)
           scanf("%s" , words[i]);
        qsort(words , n , sizeof(words[0]) , cmp);
        for(int i = 0 ; i < n ; i++){
           int x = words[i][0]-'a';
           int y = words[i][strlen(words[i])-1]-'a';
           v[x].push_back(y);
           vis[x] = vis[y] = true;
           outDegree[x]++;
           inDegree[y]++;
           father[find(x)] = find(y);
        }
        solve();
    }
    return 0;
}
时间: 2024-11-10 00:29:19

poj 2337 Catenyms的相关文章

POJ题目分类

初期: 一.基本算法:      (1)枚举. (poj1753,poj2965)      (2)贪心(poj1328,poj2109,poj2586)      (3)递归和分治法.      (4)递推.      (5)构造法.(poj3295)      (6)模拟法.(poj1068,poj2632,poj1573,poj2993,poj2996) 二.图算法:      (1)图的深度优先遍历和广度优先遍历.      (2)最短路径算法(dijkstra,bellman-ford

poj分类

初期: 一.基本算法:      (1)枚举. (poj1753,poj2965)      (2)贪心(poj1328,poj2109,poj2586)      (3)递归和分治法.      (4)递推.      (5)构造法.(poj3295)      (6)模拟法.(poj1068,poj2632,poj1573,poj2993,poj2996) 二.图算法:      (1)图的深度优先遍历和广度优先遍历.      (2)最短路径算法(dijkstra,bellman-ford

POJ:DNA Sorting 特殊的排序

Description One measure of ``unsortedness'' in a sequence is the number of pairs of entries that are out of order with respect to each other. For instance, in the letter sequence ``DAABEC'', this measure is 5, since D is greater than four letters to

POJ 1001 Exponentiation 无限大数的指数乘法 题解

POJ做的很好,本题就是要求一个无限位大的指数乘法结果. 要求基础:无限大数位相乘 额外要求:处理特殊情况的能力 -- 关键是考这个能力了. 所以本题的用例特别重要,再聪明的人也会疏忽某些用例的. 本题对程序健壮性的考查到达了变态级别了. 更多精彩内容:http://www.bianceng.cnhttp://www.bianceng.cn/Programming/sjjg/ 某人贴出的测试用例数据地址: http://poj.org/showmessage?message_id=76017 有

POJ 2240 Arbitrage:最短路 Floyd

Arbitrage:http://poj.org/problem?id=2240 大意: 给你m种货币,给你m种货币兑换规则,问通过这些规则最后能不能盈利.eg:1美元换0.5英镑,1英镑换10法郎,1法郎换0.21美元,这样1美元能换0.5*10*0.21=1.05美元,净赚0.05美元. 思路: 用Floyd找出每两种钱之间的最大兑换关系,遍历一遍,看有没有那种钱币最后能盈利,有就输出Yes,没有就是No.在处理钱币名称与编号之间的关系时,可以用map存(比较好用),当然也可以用字符串比较.

POJ 1860 Currency Exchange:最短路 Bellman-Ford

Currency Exchange:http://poj.org/problem?id=1860 大意:有多种货币,之间可以交换,但是需要手续费,也就是说既有汇率又有手续费.问经过交换之后能不能赚. 思路:Bellman_Ford,因为要求最长路,所以松弛条件改一下就好了. Tips: 3              2                  1                20.0货币的数量   兑换点的数量     主人公拥有的货币量    主人公拥有货币的价值1 2 1.00

POJ 1258 Agri-Net:最小生成树 Prim 模版题

Agri-Net:http://poj.org/problem?id=1258 大意:新镇长竞选宣言就是将网络带到每一个农场,给出农场个数,两两之间建光缆的耗费,求所有都联通的最小耗费. 思路:最小生成树,因为边比较稠密,用Prim做. PS:对于比较稠密的图,用Prim,对于比较稀疏的图,用 Kruskal.Kruskal是找边的过程,稀疏的话会比较快. 更多精彩内容:http://www.bianceng.cnhttp://www.bianceng.cn/Programming/sjjg/

POJ 1789 Truck History:最小生成树 Prim

Truck History:http://poj.org/problem?id=1789 大意:用一个7位的string代表一个编号,两个编号之间的距离代表这两个编号之间不同字母的个数.一个编号只能由另一个编号变化的来,变化的字母的数量就是这两个编号之间相应的距离,现在要找出一个变化方案,使得总代价最小,也就是距离之和最小. 思路:将每个字符串当成一个节点,求出每个节点之间需要变化的次数为边的权值,用Prim建立最小生成树(稠密图). 更多精彩内容:http://www.bianceng.cnh

POJ 2485 Highways:最小生成树 Prim

Highways:http://poj.org/problem?id=2485 大意:给你一个用邻接矩阵形式存储的有n个顶点的无向图,让你求它的最小生成树并求出在这个生成树里面最大的边的权值. 思路:用Prim求,判断条件改一下就行. PS:dis数组初始化的时候用memset一直RE,希望有知道怎么回事的不吝赐教,谢了~ 更多精彩内容:http://www.bianceng.cnhttp://www.bianceng.cn/Programming/sjjg/ #include <stdio.h