第一次写博客,以前一直没有总结过,现在开始对自己学的东西做一些记录吧,方便以后复习或者就当作留个脚印。
笔者目前大一,水平弱弱弱…有不正确的地方或者可以改进的地方还望指出。
找伙伴,有想一起学习的朋友可以一起交流交流。email: zpengst@outlook.com
题目链接:https://vjudge.net/problem/UVA-10129
题目大意:输入n个单词,判断是否能把所有单词连接成一个串,使得每个单词首字母与前一个单词尾字母相同。
思路:
1:把每个单词看作一座桥,二十六个英文字母看作节点,保存成无向图,还要记录每个节点出度入度。
2:判断整个有向图的奇点数是否大于2,大于2则不存在欧拉道路,存在则走第三步。
3:判断图的连通性,笔者目前只会用DFS(并查集还没学),看作无向图(稍微提高效率)。若连通则存在欧拉道路。
注意:
思路讲起来简洁,然而每次实现都会遇到各种问题。(笔者太弱了)
若奇点数为2,判断连通性的时候一定要注意起点是出度大于入度的那个节点。(如果要打印路径)
若奇点数为0,(容易忽略)一定要找一个存在桥的节点作为起点。
代码:
话不多说,直接上AC代码。看了下各路大神的代码,都这么短!!!都不好意思贴上来了。
不太想写注释了,代码如下。
#include<iostream> #include<string> #include<cstring> #include<cstdlib> using namespace std; bool G[26][26]; int out_cnt[26],in_cnt[26]; void dfs(int in) { for(int i=0; i<26; ++i) { if(G[in][i]) { G[in][i]=G[i][in]=false; dfs(i); } } } bool is_cncted(int in) { dfs(in); for(int i=0; i<26; ++i) for(int j=0; j<26; ++j) if(G[i][j]) return false; return true; } int main() { int n; cin>>n; while(n--) { memset(G,0,sizeof(G)); memset(out_cnt,0,sizeof(out_cnt)); memset(in_cnt,0,sizeof(in_cnt)); int t; cin>>t; string s; while(t--) { cin>>s; G[*s.begin()-'a'][*(s.end()-1)-'a']= G[*(s.end()-1)-'a'][*s.begin()-'a']=1; out_cnt[*s.begin()-'a']++; in_cnt[*(s.end()-1)-'a']++; } int sp_in=0,sp_cnt=0,flag=1; for(int i=0; i<26; ++i) if(in_cnt[i]!=out_cnt[i]) if(++sp_cnt>2||abs(in_cnt[i]-out_cnt[i])!=1) { flag=0; break; } else if(sp_cnt==1) sp_in=i; else if(in_cnt[sp_in]-out_cnt[sp_in]+in_cnt[i]-out_cnt[i]) { flag=0; break; } if(flag) for(int i=0; i<26; ++i) if(out_cnt[i]) { if(!is_cncted(i)) flag=0; break; } if(flag) cout<<"Ordering is possible."<<endl; else cout<<"The door cannot be opened."<<endl; } return 0; }