zoukankan      html  css  js  c++  java
  • POJ 2337 Catenyms (有向图欧拉路径,求字典序最小的解)

    Catenyms
    Time Limit: 1000MS   Memory Limit: 65536K
    Total Submissions: 8756   Accepted: 2306

    Description

    A catenym is a pair of words separated by a period such that the last letter of the first word is the same as the last letter of the second. For example, the following are catenyms: 
    dog.gopher
    
    gopher.rat
    rat.tiger
    aloha.aloha
    arachnid.dog

    A compound catenym is a sequence of three or more words separated by periods such that each adjacent pair of words forms a catenym. For example, 

    aloha.aloha.arachnid.dog.gopher.rat.tiger 

    Given a dictionary of lower case words, you are to find a compound catenym that contains each of the words exactly once.

    Input

    The first line of standard input contains t, the number of test cases. Each test case begins with 3 <= n <= 1000 - the number of words in the dictionary. n distinct dictionary words follow; each word is a string of between 1 and 20 lowercase letters on a line by itself.

    Output

    For each test case, output a line giving the lexicographically least compound catenym that contains each dictionary word exactly once. Output "***" if there is no solution.

    Sample Input

    2
    6
    aloha
    arachnid
    dog
    gopher
    rat
    tiger
    3
    oak
    maple
    elm
    

    Sample Output

    aloha.arachnid.dog.gopher.rat.tiger
    ***
    

    Source

     
     
     
     

    把26个小写字母当成点,每个单词就是一条边。

    然后就是求欧拉路径。

    为了保证字典序最小,要先排序,加边要按照顺序加。

    而且求解的dfs起点要选择下,选择最小的。

      1 /* ***********************************************
      2 Author        :kuangbin
      3 Created Time  :2014-2-3 13:12:43
      4 File Name     :E:2014ACM专题学习图论欧拉路有向图POJ2337.cpp
      5 ************************************************ */
      6 
      7 #include <stdio.h>
      8 #include <string.h>
      9 #include <iostream>
     10 #include <algorithm>
     11 #include <vector>
     12 #include <queue>
     13 #include <set>
     14 #include <map>
     15 #include <string>
     16 #include <math.h>
     17 #include <stdlib.h>
     18 #include <time.h>
     19 using namespace std;
     20 struct Edge
     21 {
     22     int to,next;
     23     int index;
     24     bool flag;
     25 }edge[2010];
     26 int head[30],tot;
     27 void init()
     28 {
     29     tot = 0;
     30     memset(head,-1,sizeof(head));
     31 }
     32 void addedge(int u,int v,int index)
     33 {
     34     edge[tot].to = v;
     35     edge[tot].next = head[u];
     36     edge[tot].index = index;
     37     edge[tot].flag = false;
     38     head[u] = tot++;
     39 }
     40 string str[1010];
     41 int in[30],out[30];
     42 int cnt;
     43 int ans[1010];
     44 void dfs(int u)
     45 {
     46     for(int i = head[u] ;i != -1;i = edge[i].next)
     47         if(!edge[i].flag)
     48         {
     49             edge[i].flag = true;
     50             dfs(edge[i].to);
     51             ans[cnt++] = edge[i].index;
     52         }
     53 }
     54 int main()
     55 {
     56     //freopen("in.txt","r",stdin);
     57     //freopen("out.txt","w",stdout);
     58     int T,n;
     59     scanf("%d",&T);
     60     while(T--)
     61     {
     62         scanf("%d",&n);
     63         for(int i = 0;i < n;i++)
     64             cin>>str[i];
     65         sort(str,str+n);//要输出字典序最小的解,先按照字典序排序
     66         init();
     67         memset(in,0,sizeof(in));
     68         memset(out,0,sizeof(out));
     69         int start = 100;
     70         for(int i = n-1;i >= 0;i--)//字典序大的先加入
     71         {
     72             int u = str[i][0] - 'a';
     73             int v = str[i][str[i].length() - 1] - 'a';
     74             addedge(u,v,i);
     75             out[u]++;
     76             in[v]++;
     77             if(u < start)start = u;
     78             if(v < start)start = v;
     79         }
     80         int cc1 = 0, cc2 = 0;
     81         for(int i = 0;i < 26;i++)
     82         {
     83             if(out[i] - in[i] == 1)
     84             {
     85                 cc1++;
     86                 start = i;//如果有一个出度比入度大1的点,就从这个点出发,否则从最小的点出发
     87             }
     88             else if(out[i] - in[i] == -1)
     89                 cc2++;
     90             else if(out[i] - in[i] != 0)
     91                 cc1 = 3;
     92         }
     93         if(! ( (cc1 == 0 && cc2 == 0) || (cc1 == 1 && cc2 == 1) ))
     94         {
     95             printf("***
    ");
     96             continue;
     97         }
     98         cnt = 0;
     99         dfs(start);
    100         if(cnt != n)//判断是否连通
    101         {
    102             printf("***
    ");
    103             continue;
    104         }
    105         for(int i = cnt-1; i >= 0;i--)
    106         {
    107             cout<<str[ans[i]];
    108             if(i > 0)printf(".");
    109             else printf("
    ");
    110         }
    111     }
    112     return 0;
    113 }
  • 相关阅读:
    shell脚本
    vim使用快捷键
    logback.xml_appender配置
    vim配置文件
    sed
    使用linux服务器安装wordpress博客详细教程
    JDBC为什么要使用PreparedStatement而不是Statement
    Jsp技术介绍
    jsp的appilication.getInitParameter()方法无法获取到值的问题
    ubuntu 插网线无法上网解决方案
  • 原文地址:https://www.cnblogs.com/kuangbin/p/3537544.html
Copyright © 2011-2022 走看看