nyoj99(并查集+欧拉路+dfs)

2024-09-08 02:48
文章标签 dfs 查集 欧拉 nyoj99

本文主要是介绍nyoj99(并查集+欧拉路+dfs),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

单词拼接

时间限制: 3000 ms  |  内存限制: 65535 KB
难度: 5
描述

给你一些单词,请你判断能否把它们首尾串起来串成一串。

前一个单词的结尾应该与下一个单词的道字母相同。

aloha

dog

arachnid

gopher

tiger

rat

 

可以拼接成:aloha.arachnid.dog.gopher.rat.tiger

输入
第一行是一个整数N(0<N<20),表示测试数据的组数
每组测试数据的第一行是一个整数M,表示该组测试数据中有M(2<M<1000)个互不相同的单词,随后的M行,每行是一个长度不超过30的单词,单词全部由小写字母组成。
输出
如果存在拼接方案,请输出所有拼接方案中字典序最小的方案。(两个单词之间输出一个英文句号".")
如果不存在拼接方案,则输出
***
样例输入
2
6
aloha
arachnid
dog
gopher
rat
tiger
3
oak
maple
elm
样例输出
aloha.arachnid.dog.gopher.rat.tiger
***

这题真心是好题,我做了整整2天终于给AC了,poj的题真心难!+_=

解题思路:

首先你必须将这道题建模成一个图,它只是第一个字母和最后一个字母接龙,所以只要用个结构体将他们单独取出,这是第一步,然后就需要判断这个图是不是连通图,

所以很自然想到并查集,但连通也会与很多种,也许有环,所以你又需要用欧拉路的定义来判断,当这些都满足了你只做到了第二步,这些字母可能会有重复的,

j就像这样(asdf,ajfhsdf),没法你又要对图进行深度遍历,在遍历时将通路的所有字符转存到另外个数组str[1002][35];这算是完了,但你要考虑输出的格式和这个字符数组中的值是什么序列的,所以建议自己单步调试下,这样你会更加明白!

代码如下(大部分函数都有注释):

#include<iostream>
#include<string>
#include<string.h>
#include<algorithm>
using namespace std;char c[35],str[1002][35];
int number=0,pre[27],vis[27],cnt=0;
int in_du[27],out_du[27];
struct word1
{int star,end;int vis;//是否访问过char s[30];
}word[1002];bool cmp(word1 p, word1 q)
{return strcmp(p.s ,q.s)==-1; 
}//排序字符串的函数void serch(char *c)//初始化结构体数组函数
{int len=strlen(c);strcpy(word[number].s,c);word[number].vis=0;//初始该点未访问word[number].star=c[0]-'a'+1;out_du[c[0]-'a'+1]++;//出度自加word[number].end=c[len-1]-'a'+1;in_du[c[len-1]-'a'+1]++;//入度自加number++;
}int find1(int a)//并查集查找函数
{while(a!=pre[a])a=pre[a];return a;
}void join(int x,int y)//并查集连接函数
{x=find1(x);y=find1(y);if(x!=y)pre[x]=y;}void dfs(int x)//深度遍历
{for(int i=0;i<number;i++){if(!word[i].vis&&x==word[i].star){word[i].vis=1;//表示该点访问过dfs(word[i].end);//递归strcpy(str[cnt++],word[i].s);//将访问过的点都放如str数组中}}
}int main()
{int n,m,i;cin>>n;while(n--){bool flag=1;int flag1=0,flag2=0;cin>>m;if(m==0)flag=0;for(i=0;i<m;i++){cin>>c;serch(c);//输入在word结构体数组中}for(i=0;i<27;i++)//初始化并查集{pre[i]=i;vis[i]=0;//初始化访问数组}for(i=0;i<number;i++)//并查集实现{join(word[i].star,word[i].end);vis[word[i].end]=vis[word[i].star]=1;}int count =0;for(i=0;i<27&&flag;i++){if(vis[i]&&pre[i]==i)//查找根节点,若连通则count必为1count++;if(vis[i]&&in_du[i]!=out_du[i])//对每个点的入度和出度统计,判断是否存在有向图欧拉路{if(in_du[i]-out_du[i]==1)flag1++;else if (out_du[i]-in_du[i]==1)flag2++;else flag=0;}}if(count==1&&flag&&((flag1==0&&flag2==0)||(flag1==1&&flag2==1)) )//如果有向图连通且存在欧拉路{sort(word,word+number,cmp);	int start=word[0].star;for(i=0;i<27;i++){if(vis[i]&&out_du[i]==in_du[i]+1)//找到欧拉路的开始位置即出度比入度大1的点{start=i;break;}}dfs(start);//遍历图for(i=cnt-1;i>0;i--)cout<<str[i]<<'.';cout<<str[0];cout<<endl;}elsecout<<"***"<<endl;number=0;cnt=0;memset(in_du,0,sizeof(in_du));memset(out_du,0,sizeof(out_du));memset(vis,0,sizeof(vis));}return 0;
}



这篇关于nyoj99(并查集+欧拉路+dfs)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1146897

相关文章

hdu 2489 (dfs枚举 + prim)

题意: 对于一棵顶点和边都有权值的树,使用下面的等式来计算Ratio 给定一个n 个顶点的完全图及它所有顶点和边的权值,找到一个该图含有m 个顶点的子图,并且让这个子图的Ratio 值在所有m 个顶点的树中最小。 解析: 因为数据量不大,先用dfs枚举搭配出m个子节点,算出点和,然后套个prim算出边和,每次比较大小即可。 dfs没有写好,A的老泪纵横。 错在把index在d

uva 1342 欧拉定理(计算几何模板)

题意: 给几个点,把这几个点用直线连起来,求这些直线把平面分成了几个。 解析: 欧拉定理: 顶点数 + 面数 - 边数= 2。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#inc

poj 3050 dfs + set的妙用

题意: 给一个5x5的矩阵,求由多少个由连续6个元素组成的不一样的字符的个数。 解析: dfs + set去重搞定。 代码: #include <iostream>#include <cstdio>#include <set>#include <cstdlib>#include <algorithm>#include <cstring>#include <cm

poj 1182 并查集 食物链类

题意: 有n只动物,分别编号1....n。所有动物都属于A,B,C中的一种,已知A吃B,B吃C,C吃A。 按顺序给出下面两种共K条信息: 1. x 和 y 属于同一类。 2. x 吃 y 。 然而这些信息可能会出错,有可能有的信息和之前给出的信息矛盾,也有的信息可能给出的 x 和 y 不在n的范围内。 求k条信息中有多少条是不正确的。 解析: 对于每只动物,创建3个元素 i

POJ1988带权并查集

M u v 将u所在的堆移动到v所在的堆的上面 C u 求u的下面有多少块 带权并查集 import java.io.BufferedReader;import java.io.InputStream;import java.io.InputStreamReader;import java.io.PrintWriter;import java.math.BigInteger;i

POJ1703带权并查集

D: u v  u与v在不同的集合 A: u v  查询u与v的关系 1)压缩路径过程        fu->root   0  1  u-fu 0                 0  1   1                 1  0 2)合并过程 fu->fv      u->fu   0 1   v->fv 0            1 0 1            0

ural 1149. Sinus Dances dfs

1149. Sinus Dances Time limit: 1.0 second Memory limit: 64 MB Let  An = sin(1–sin(2+sin(3–sin(4+…sin( n))…) Let  Sn = (…( A 1+ n) A 2+ n–1) A 3+…+2) An+1 For given  N print  SN Input One

hdu 6198 dfs枚举找规律+矩阵乘法

number number number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Problem Description We define a sequence  F : ⋅   F0=0,F1=1 ; ⋅   Fn=Fn

深度优先(DFS)和广度优先(BFS)——算法

深度优先 深度优先搜索算法(英语:Depth-First-Search,DFS)是一种用于遍历或搜索树或图的算法。 沿着树的深度遍历树的节点,尽可能深的搜索树的分支,当节点v的所在边都己被探寻过,搜索将回溯到发现节点v的那条边的起始节点。这一过程一直进行到已发现从源节点可达的所有节点为止。如果还存在未被发现的节点,则选择其中一个作为源节点并重复以上过程,整个进程反复进行直到所有节点都被访

欧拉系统 kernel 升级、降级

系统版本  cat  /etc/os-release  NAME="openEuler"VERSION="22.03 (LTS-SP1)"ID="openEuler"VERSION_ID="22.03"PRETTY_NAME="openEuler 22.03 (LTS-SP1)"ANSI_COLOR="0;31" 系统初始 kernel 版本 5.10.0-136.12.0.