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. Java_冒泡排序_原理及优化

    冒泡排序及其优化 一.原理及优化原理 1.原理讲解 冒泡排序即:第一个数与第二个数进行比较,如果满足条件位置不变,再把第二个数与第三个数进行比较.不满足条件则替换位置,再把第二个数与第三个数进行比较, ...

  2. Josephu(约瑟夫)问题解析

    Josephu问题为: 设置编号为1,2,3,......n的n个人围坐一圈,约定编号为k(1<=k<=n)的人从1看是报数,数到m的那个人出列,它的下一位又从1开始报数,数到m的那个人出 ...

  3. python基础学习(十二)变量进阶

    目录 1. 变量的引用 1.1 引用的概念 1.2 变量引用 的实例 1.3 函数的参数和返回值的传递 2. 可变和不可变类型 哈希 (hash) 3. 局部变量和全局变量 3.1 局部变量 3.2 ...

  4. python基础学习(五)while循环语句

    while循环基本使用 循环的作用就是让指定的代码重复的执行 while循环最常用的应用场景就是让执行的代码按照指定的次数重复执行 流程图 基本语法 初始条件设置 —— 通常是重复执行的 计数器 wh ...

  5. JDK的动态代理-----为接口进行代理

    JDK的动态代理是必须掌握的,动态代理的好处就不用我多说了吧 :) 小弟最近在研究mybatis的源码实现,就开始了解mybatis的Mapper代理机制,为什么接口不用实现类也能代理? 好了,废话不 ...

  6. 如何使用@vue/cli 3.0在npm上创建,发布和使用你自己的Vue.js组件库

    译者按: 你可能npm人家的包过成千上万次,但你是否有创建,发布和使用过自己的npm包? 原文: How to create, publish and use your own VueJS Compo ...

  7. JavaScript机器学习之线性回归

    译者按: AI时代,不会机器学习的JavaScript开发者不是好的前端工程师. 原文: Machine Learning with JavaScript : Part 1 译者: Fundebug ...

  8. 2018-11-04 在线代码离线翻译Chrome插件"一马"v0.0.14

    续前文: 在线代码离线翻译Chrome插件"一马"v0.0.8. 主要改进如下. 项目源码库: program-in-chinese/webextension_github_cod ...

  9. div 中图片溢出问题及 CSS3中图片翻转问题

    如果设置一个div 装两张以上的图片,如果不设置好div的宽度和高度,就会使图片溢出. 我们知道,div是可以由图片撑开其宽高的,也就是说如果只放一张图片的情况下,不设置div的宽高,div的宽高会默 ...

  10. 利用Fiddler修改请求信息通过Web API执行Dynamics 365操作(Action)实例

    本人微信和易信公众号: 微软动态CRM专家罗勇 ,回复261或者20170724可方便获取本文,同时可以在第一间得到我发布的最新的博文信息,follow me!我的网站是 www.luoyong.me ...