说在前面

M↓写的第一篇题解,欢迎提出意见.

题目描述

瑞瑞有一堆的玩具木棍,每根木棍的两端分别被染上了某种颜色,现在他突然有了一个想法,想要把这些木棍连在一起拼成一条线,并且使得木棍与木棍相接触的两端颜色都是相同的,给出每根木棍两端的颜色,请问是否存在满足要求的排列方式。

例如,如果只有 \(2\) 根木棍,第一根两端的颜色分别为 red, blue,第二根两端的颜色分别为 red, yellow,那么 blue---red | red----yellow 便是一种满足要求的排列方式。

输入格式

输入有若干行,每行包括两个单词,表示一根木棍两端的颜色,单词由小写字母组成,且单词长度不会超过 \(10\) 个字母,最多有 \(250000\) 根木棍。

输出格式

如果木棒能够按要求排列,输出 Possible,否则输出 Impossible

输入输出样例

输入 #1

blue red
red violet
cyan blue
blue magenta
magenta cyan

输出 #1

Possible

分析

一根木棒就相当于一条边,木棒两边的颜色就是这条边所连的点,所以此题就是问一张图是否存在欧拉路。

欧拉路的判定很简单——所有点都连通(并查集),最多两个点的度为奇数(一个数组就可以搞定)。

那么这道题之所以是蓝题,是因为它对时间要求很严格——最多2.5e6个木棒,以及读入的字符串的处理。

字符串的处理

这里最最最快的方式是用\(trie\)。

\(trie\)中每个节点都有两个元素,\(num\)标记和\(26\)个指针,这里我们用数组模拟指针:

  1. 设\(0\)是根节点,实际上不代表任何的字母
  2. 对于要加入的每一个字符串,逐位考虑
  3. 如果当前节点没有str[i]这个子节点的话就新建一个节点为子节点
  4. 跳转到这个子节点,判断下一位
  5. 重复3、4步骤
  6. 如果最终的节点没有被分配一个编号的话,那么这个就新建一个编号给这个终节点

这样每一个字符串都有了唯一的编号,且编号是连续的,方便开数组等后续操作。

这就完成了trie的部分——字符串到正整数的映射。

struct Trie
{
int son[26],num;
}trie[2000010];
int n,trie_cnt;
int insert(string str)
{
int now=0;
for(int i=0;i<str.size();i++)
{
if(!trie[now].son[str[i]-'a']) trie[now].son[str[i]-'a']=++trie_cnt;
now=trie[now].son[str[i]-'a'];
}
if(!trie[now].num) trie[now].num=++n;
return trie[now].num;
}

可能有人会问为什么不用\(map\)?

因为\(map\)每次插入是\(logn\)的,而\(trie\)每次插入与字符串的长度有关(看作\(O(1)\)就好),题目也说了每个单词不超过\(10\)个字母。

当然也可以用\(unordered_map\)(需要C++11!),不会\(STL\)的同学可以用\(hash\)(这个还是有点慢)。

所以这里最优的就是\(trie\)啦!

判断欧拉路

欧拉路有个经典的故事——七桥问题,相信你应该耳熟能详了。

即:经过每条边正好一次,能不能把所有边都走一遍?

可以证明,只要整个图是连通的,且有奇数度的点不超过两个,那么就存在欧拉路!

  • 度的统计只需要在读入木棒的时候标记一下即可。

  • 判断连通图用并查集

读入

while(cin>>str)
{
x=insert(str);
cin>>str;
y=insert(str);
merge(x,y);
degree[x]++;
degree[y]++;
}

判断

判断这里我用了点小技巧,同时判断度和并查集。

  • 如果有相邻的两项的祖先是不同的,那么这肯定不是连通图,给flag加上一个大数字。
  • 如果这点的度是奇数,那么flag+1就好。
  • 最后判断flag,大于2说明奇度点多了或者图不连通,即不可能有欧拉路,反正则存在。
int flag=(degree[1]&1);
for(int i=2;i<=n;i++)
{
if(getf(i)!=getf(i-1)) flag+=10;
if(degree[i]&1) flag++;
}
if(flag>2) cout<<"Impossible"<<endl;
else cout<<"Possible"<<endl;

Code

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<queue>
#include<vector>
#define IL inline
#define re register
#define LL long long
#define ULL unsigned long long
#define re register
#define debug printf("Now is %d\n",__LINE__);
using namespace std; template<class T>inline void read(T&x)
{
char ch=getchar();
while(!isdigit(ch))ch=getchar();
x=ch-'0';ch=getchar();
while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
}
inline int read()
{
int x=0;
char ch=getchar();
while(!isdigit(ch))ch=getchar();
x=ch-'0';ch=getchar();
while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
return x;
}
int G[55];
template<class T>inline void write(T x)
{
int g=0;
if(x<0) x=-x,putchar('-');
do{G[++g]=x%10;x/=10;}while(x);
for(re int i=g;i>=1;--i)putchar('0'+G[i]);putchar('\n');
} struct Trie
{
int son[26],num;
}trie[2000010];
int n,trie_cnt;
int insert(string str)
{
int now=0;
for(int i=0;i<str.size();i++)
{
if(!trie[now].son[str[i]-'a']) trie[now].son[str[i]-'a']=++trie_cnt;
now=trie[now].son[str[i]-'a'];
}
if(!trie[now].num) trie[now].num=++n;
return trie[now].num;
}
int f[500010];
int getf(int x)
{
while(x!=f[x]) x=f[x];
return x;
}
void merge(int x,int y)
{
x=getf(x);
y=getf(y);
f[x]=y;
}
int degree[500010];
int main()
{
string str;
int x,y;
for(int i=1;i<=500000;i++) f[i]=i;
while(cin>>str)
{
x=insert(str);
cin>>str;
y=insert(str);
merge(x,y);
degree[x]++;
degree[y]++;
}
int flag=(degree[1]&1);
for(int i=2;i<=n;i++)
{
if(getf(i)!=getf(i-1)) flag+=10;
if(degree[i]&1) flag++;
}
if(flag>2) cout<<"Impossible"<<endl;
else cout<<"Possible"<<endl;
return 0;
}

注意

在洛谷上提交的话,如果你\(#2\)无法通过,请注意数组大小问题:

最多有\(2.5e6\)根木棒,意味着最多有\(5e6\)种单词,所以数组要开到\(5e6\),而\(trie\)数组越大越好。

经过我的非精确计算,类似于线段树,每一层新建分支\(26\),最多\(10\)层,(最多\(141,167,095,653,376\)个叶子节点),而题目中有单词数量不超过\(2.5e6\),\(26^4=456976\),应该开到最多\(26+676+17576+2500000≈2,518,278\)即可。(这个是乱算的)

疑惑

如果出现,有两根相同的木棒怎么办?题目中并没有否认这种情况,但是不这样判断的话也过了啊……奇怪啊。

如果以后这道题修改或者加强了,请来踢我一脚(

洛谷P1333 瑞瑞的木棍 字符串 最短路的更多相关文章

  1. 洛谷P1333 瑞瑞的木棍(欧拉回路)

    题目描述 瑞瑞有一堆的玩具木棍,每根木棍的两端分别被染上了某种颜色,现在他突然有了一个想法,想要把这些木棍连在一起拼成一条线,并且使得木棍与木棍相接触的两端颜色都是相同的,给出每根木棍两端的颜色,请问 ...

  2. 洛谷 P4036 [JSOI2008]火星人(splay+字符串hash)

    题面 洛谷 题解 首先,我们知道求最长公共前缀可以用二分答案+hash来求 因为有修改操作, 考虑将整个字符串的hash值放入splay中 接着就是splay的基本操作了 Code #include& ...

  3. 洛谷 P3263 [JLOI2015]有意义的字符串

    洛谷 首先,看到\((\frac{(b+\sqrt{d})}{2})^n\),很快能够想到一元二次方程的解\(\frac{-b\pm\sqrt{\Delta}}{2a}\). 所以可以推出,\(\fr ...

  4. 洛谷 P1308 统计单词数【字符串+模拟】

    P1308 统计单词数 题目描述 一般的文本编辑器都有查找单词的功能,该功能可以快速定位特定单词在文章中的位置,有的还能统计出特定单词在文章中出现的次数. 现在,请你编程实现这一功能,具体要求是:给定 ...

  5. 洛谷P3234 抄卡组 [HNOI2014] 字符串hash

    正解:字符串hash 解题报告: 传送门! 字符串hash是字符串匹配中很常见的一个方法,原理也很好懂,这里就不做太多阐述辣有时间放到hash笔记里面去QAQ 题意不说了挺好理解的,自带一句话概括好评 ...

  6. 洛谷P3538 [POI2012]OKR-A Horrible Poem [字符串hash]

    题目传送门 A Horrible Poem 题目描述 Bytie boy has to learn a fragment of a certain poem by heart. The poem, f ...

  7. 洛谷 P1308 统计单词数【字符串处理】

    题目描述 一般的文本编辑器都有查找单词的功能,该功能可以快速定位特定单词在文章中的位置,有的还能统计出特定单词在文章中出现的次数. 现在,请你编程实现这一功能,具体要求是:给定一个单词,请你输出它在给 ...

  8. 洛谷P1781 宇宙总统【排序+字符串】

    地球历公元6036年,全宇宙准备竞选一个最贤能的人当总统,共有n个非凡拔尖的人竞选总统,现在票数已经统计完毕,请你算出谁能够当上总统. 输入输出格式 输入格式: president.in 第一行为一个 ...

  9. 洛谷P1603——斯诺登的密码(字符串处理)

    https://www.luogu.org/problem/show?pid=1603#sub 题目描述 2013年X月X日,俄罗斯办理了斯诺登的护照,于是他混迹于一架开往委内瑞拉的飞机.但是,这件事 ...

  10. 洛谷P5292 [HNOI2019]校园旅行(二分图+最短路)

    题面 传送门 题解 如果暴力的话,我们可以把所有的二元组全都扔进一个队列里,然后每次往两边更新同色点,这样的话复杂度是\(O(m^2)\) 怎么优化呢? 对于一个同色联通块,如果它是一个二分图,我们只 ...

随机推荐

  1. SVG path 标签根据两点和角度绘制弧线

    同步发布:https://blog.jijian.link/2020-04-14/svg-arc/ 由于功能受限,此处不能放 iframe 嵌入链接,如需看到实时效果,请移步 https://blog ...

  2. wps时间戳转换成日期

    第一步 打开WPS表格,选择空表格 第二步 右击选择"设置单元格格式" 第三步 选择"日期",然后选择需要的日期类型 第四步 然后在表格里,输入公式 =(D2/ ...

  3. go math/rand包详解

    go math/rand package rand import "math/rand" rand包实现了伪随机数生成器. math_rand go官方标准文档 随机数从资源生成. ...

  4. 用状态模式开发一个基于WPF的截图功能

    状态模式 状态模式是设计模式中的一种行为设计模式,对很多人来说,这个模式平时可能用不到.但是如果你做游戏开发的话,我相信你应该对这个模式有一个很深刻的理解.状态模式在游戏中开发中还是比较常见的.状态模 ...

  5. 初始化参数之memory_target

    一.引言: Oracle 9i引入pga_aggregate_target,可以自动对PGA进行调整: Oracle 10g引入sga_target,可以自动对SGA进行调整: Oracle 11g则 ...

  6. 【网络攻防】ARP欺骗实验

    实验概述 ARP欺骗是一类地址欺骗类病毒,属于木马病毒,自身不具备主动传播的特性,不会自我复制.但是由于其发作的时候会不断向全网发送伪造的ARP数据包,导致网络无法正常运行,严重的甚至可能带来整个网络 ...

  7. STLINK/JLINK USB识别不稳定问题的解决

    第一阶段:自己基于STM32F103C8T6的STLINK,调试一直正常. 第二阶段:发现了硬汉的教程,基于JLINK的RTT viewer 代替串口打印调试信息,所以购买了JLINK,手里的STLI ...

  8. 机器人操作系统ROS2之安装(Ubuntu 24)

    根据官网说明,ROS2是支持MAC的,本来打算在手头的MAC 15.3.2装一个,虽然要自己编译ROS2系统,但是想着比虚拟机性能好,就兴冲冲的开始了,也没在意官网提示尽量还是装安装版.最后折腾了几天 ...

  9. 查看MySQL是否安装成功

    1)安装了Windows Service:MySQL80,并且已经启动. 2)安装了MySQL软件.安装位置为:C:\Program Files\MySQL  (默认路径) (MySQL文件下放的是软 ...

  10. nim 语言使用 concept 实现 c# 的interface

    nim简介 nim语言兼顾C#等高级语言语义表达的丰富性,又有 C 语言的灵活性,以及超强的性能.下面是中文站对他的总结,我抄下来: Nim 是一种静态类型的.编译型.系统编程语言.它结合了其他成熟语 ...