Problem 洛谷P1127-词链

Accept: 256    Submit: 1.3k
Time Limit: 1000 mSec    Memory Limit : 128MB

Problem Description

如果单词 XXX 的末字母与单词 YYY 的首字母相同,则 XXX 与 YYY 可以相连成 X.YX.YX.Y 。(注意: XXX 、 YYY 之间是英文的句号“.”)。例如,单词dog与单词gopher,则doggopher可以相连成dog.gopher

另外还有一些例子:

dog.gopher

gopher.rat

rat.tiger

aloha.aloha

arachnid.dog

连接成的词可以与其他单词相连,组成更长的词链,例如:

aloha.arachnid.dog.gopher.rat.tiger

注意到,“.”两边的字母一定是相同的。

现在给你一些单词,请你找到字典序最小的词链,使得这些单词在词链中出现且仅出现一次。

 Input

第一行是一个正整数 n(1≤n≤1000),代表单词数量。

接下来共有 n行,每行是一个由 1到 20 个小写字母组成的单词

 Output

只有一行,表示组成字典序最小的词链,若不存在则只输出三个星号“ ∗∗∗”

 

 Sample Input

6
aloha
arachnid
dog
gopher
rat
tiger

 Sample Output

aloha.arachnid.dog.gopher.rat.tiger
 
题目链接:https://www.luogu.org/problemnew/show/P1127
 
这个题做的很差,感觉很简单,可能还是学艺不精。
 
剪枝的方式还是值得一提的,这个题乍一看上去没有剪枝的思路,当把整个链和欧拉路径联系起来思路自然就出来了。
统计每个字符串首尾字母出现次数,在首位出现就++,在末位就--,如果能够连成词链,那么每个字母的统计值只能位0或1,并且如果有1只能是同时有两个,
据此可以作为充要条件判断是否有解。与此同时,一个剪枝的方式也就出来了,如果是一个+1,一个-1的情况,那么+1的那个必定时开头,避免了很多无用的搜索。
字典序的问题还是非常简单的,先按字典序sort一下,链式前向星存图,因此加边的时候倒着来就好,遇到词链就输出,退出程序。
 
还有一个神奇的地方,就是abc和abcb的情况,虽然abc < abcb,但是如果有一个c、b 接上去就成了abcc...、abcbb...
好像用上述算法还是有问题的,原来还听老师讲过一个类似的题,也是这种情况下有点问题,不过都能AC...
 
 
 #include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <string>
#include <stack>
#include <algorithm>
using namespace std; const int maxn = +;
const int maxm = maxn*maxn; int n,tot,head[maxn];
int len[maxn];
bool vis[maxn];
string str[maxn]; struct Edge{
int to,next;
Edge(int to = ,int next = ) : to(to),next(next) {}
}edge[maxm<<]; void AddEdge(int u,int v){
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++;
} int top,sta[maxn<<]; void output(){
cout << str[sta[]];
for(int i = ;i <= n;i++){
printf(".");
cout << str[sta[i]];
}
cout << endl;
exit();
} void dfs(int u){
vis[u] = true;
sta[++top] = u;
for(int i = head[u];i != -;i = edge[i].next){
int v = edge[i].to;
if(!vis[v]) dfs(v);
}
if(top == n) output();
vis[u] = false;
top--;
} const int kind = ;
int con[maxn]; int main()
{
//freopen("input.txt","r",stdin);
cin >> n;
for(int i = ;i <= n;i++){
cin >> str[i];
}
sort(str+,str++n);
top = ;
memset(head,-,sizeof(head));
memset(vis,false,sizeof(vis));
memset(con,,sizeof(con));
for(int i = ;i <= n;i++){
len[i] = str[i].size();
}
for(int i = ;i <= n;i++){
for(int j = n;j >= ;j--){
if(i!=j && str[i][len[i]-] == str[j][]){
AddEdge(i,j);
}
}
}
for(int i = ;i <= n;i++){
con[str[i][]-'a']++;
con[str[i][len[i]-]-'a']--;
}
int head = -,cnt = ,_cnt = ;
for(int i = ;i < kind;i++){
if(con[i] == ){
head = i;
cnt++;
}
else if(con[i] == -){
_cnt++;
}
}
if(cnt== && _cnt==){
for(int i = ;i <= n;i++){
dfs(i);
}
}
else if(cnt== && _cnt==){
for(int i = ;i <= n;i++){
if(str[i][]-'a' == head) dfs(i);
}
}
printf("***\n");
return ;
}
 

洛谷P1127-词链的更多相关文章

  1. P1127 词链

    P1127 词链 题目描述 如果单词X的末字母与单词Y的首字母相同,则X与Y可以相连成X.Y.(注意:X.Y之间是英文的句号“.”).例如,单词dog与单词gopher,则dog与gopher可以相连 ...

  2. 【算法学习】【洛谷】树链剖分 & P3384 【模板】树链剖分 P2146 软件包管理器

    刚学的好玩算法,AC2题,非常开心. 其实很早就有教过,以前以为很难就没有学,现在发现其实很简单也很有用. 更重要的是我很好调试,两题都是几乎一遍过的. 介绍树链剖分前,先确保已经学会以下基本技巧: ...

  3. 洛谷P3384 树链剖分

    如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节点的值都加上z 操作2: 格式: 2 x ...

  4. 洛谷 P3384 树链剖分(模板题)

    题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节点的值都加上z 操作2: 格式 ...

  5. 【树链剖分】洛谷P3379 树链剖分求LCA

    题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每 ...

  6. 洛谷 4115 Qtree4——链分治

    题目:https://www.luogu.org/problemnew/show/P4115 论文:https://wenku.baidu.com/view/1bc2e4ea172ded630b1cb ...

  7. 洛谷P2146 树链剖分

    题意 思路:直接树链剖分,用线段树维护即可,算是树剖的经典题目吧. 代码: #include <bits/stdc++.h> #define ls(x) (x << 1) #d ...

  8. 洛谷 [P3384] 树链剖分 模版

    支持各种数据结构上树,注意取膜. #include <iostream> #include <cstring> #include <algorithm> #incl ...

  9. 洛谷 P3384树链剖分 题解

    题面 挺好的一道树剖模板: 首先要学会最模板的树剖: 然后这道题要注意几个细节: 初始化时,seg[0]=1,seg[root]=1,top[root]=root,rev[1]=root; 在线段树上 ...

  10. 树链剖分详解(洛谷模板 P3384)

    洛谷·[模板]树链剖分 写在前面 首先,在学树链剖分之前最好先把 LCA.树形DP.DFS序 这三个知识点学了 emm还有必备的 链式前向星.线段树 也要先学了. 如果这三个知识点没掌握好的话,树链剖 ...

随机推荐

  1. 【转】消除代码中的 if-else/switch-case

    在很多时候,我们代码中会有很多分支,而且分支下面的代码又有一些复杂的逻辑,相信很多人都喜欢用 if-else/switch-case 去实现.做的不好的会直接把实现的代码放在 if-else/swit ...

  2. 列表 ul ol dl 和 块级标签和行及标签之间的转换

    1. 无序列表 有序列表 自定义列表 1,无序列表 第一 你不必须有子标签  <li></li> 第二 ul天生自带内外边距 List-style的属性值 circle(空心圆 ...

  3. C#设计模式之三抽象工厂模式(AbstractFactory)【创建型】

    一.引言 写了3篇有关设计模式的文章了,大家有了些反馈,说能从中学到一些东西,我感到很欣慰,那就继续努力.今天我要写第四个模式了,该模式叫抽象工厂.上一篇文章我们讲了[工厂方法]模式,它是为了解决[简 ...

  4. Web前端开发必备

    前端学习相关书籍 关于书籍 HTML.CSS 类别书籍,都是大同小异,在当当网.卓越网搜索一下很多推荐.如果感觉学的差不多了,可以关注一下<CSS禅意花园>,这个很有影响力. Javasc ...

  5. C#基础(201)--常量枚举

    本文知识点: 1.掌握常量的定义和使用方法 2.理解枚举的作用和特点 3.掌握枚举的使用方法 1.1.常量的定义语法 const  数据类型   常量名称  =  值: 1.2.常见错误 1.3常量的 ...

  6. Android IPC机制(三)使用AIDL实现跨进程方法调用

    上一篇文章中我们介绍了使用Messenger来进行进程间通信的方法,但是我们能发现Messenger是以串行的方式来处理客户端发来的信息,如果有大量的消息发到服务端,服务端仍然一个一个的处理再响应客户 ...

  7. 编程经验点滴----巧妙解决 Oracle NClob 读写问题

    最近一个新项目中,尝试在 Oracle 数据库中使用 NCLOB 来保存大的 xml 字符串. 在代码自动生成工具(通过 JDBC 驱动程序,读数据库表结构,自动生成对应的 java 代码,包含增加. ...

  8. Scrapy实现腾讯招聘网信息爬取【Python】

    一.腾讯招聘网 二.代码实现 1.spider爬虫 # -*- coding: utf-8 -*- import scrapy from Tencent.items import TencentIte ...

  9. Linux系统修改日期时间

    linux修改时间   服务器时间与网络时间不符: 一.手动修改 1. date命令:查看当前时间 2. date -s  时分秒 :修改时间 还需要把日期改过来 3. date -s  完整日期时间 ...

  10. Sql2012如何将远程服务器数据库及表、表结构、表数据导入本地数据库

    1.第一步,在本地数据库中建一个与服务器同名的数据库 2.第二步,右键源数据库,任务>导出数据,弹出导入导出提示框,点下一步继续 3.远程数据库操作,确认服务器名称(服务器地址).身份验证(输入 ...