题解 UVA10129 【单词 Play on Words】

· · 题解

几乎是个模板题w

很容易能看出来这是道欧拉回路板子。回想我们小学学过的的一笔画问题,那是解决无向图的欧拉回路的,所以不能用在此题,关于有向图的欧拉回路定义如下:

$2.$除两个节点外,其它节点全部满足1。而这两个节点其中一个的入度比出度大1,另一个的出度比入度大1 是不是很好理解呢qwq 所以本题思路就出来了:连边只需要看头和尾。由于是一笔画,所以要先判断是否只有一个连通块,用道法术或者并查集都能轻松解决。如果符合就判断它的入度出度也是否符合欧拉回路即可,写起来很简单 注释都在代码里了,照着那两条规定判断即可 ```cpp #include<bits/stdc++.h> using namespace std; string l[1000010]; bool vis[27];//是否访问 int in[27], out[27], fa[27];//入度,出度,祖先 int find(int x) //并查集的查询操作 { return fa[x] == x?x:find(fa[x]); } int main() { int t; cin>>t; while(t --) //T组数据 { int n; cin>>n; memset(vis, false, sizeof(vis)); for(int i = 1; i <= 26;i ++) fa[i] = i;//并查集初始化 for(int i = 1; i <= n; i++) { cin>>l[i]; in[l[i][l[i].size() - 1] - 'a' + 1] ++;//入度+1 out[l[i][0] - 'a' + 1] ++;//出度+1 vis[l[i][l[i].size() - 1] - 'a' + 1] = vis[l[i][0] - 'a' + 1] = true;//标记为访问 int x = find(l[i][l[i].size() - 1] - 'a' + 1);//找祖宗 int y = find(l[i][0] - 'a' + 1);//找祖宗 if (x != y) fa[x] = y;//合并 } int cnt = 0;//初始化为0 for (int i = 1; i <= 26;i ++)if(vis[i] and find(i) == i)cnt ++;//如果自己是祖先cnt+1 if (cnt > 1) //如果有多个连通块无解 { puts("The door cannot be opened."); continue; } vector<int>ll; for (int i = 1;i <= 26;i ++)if(vis[i] and in[i] != out[i])ll.push_back(i); if (ll.size() != 0 and ll.size() != 2) //如果大小不为0或2无解 { cout<<"The door cannot be opened."<<endl; } else if (ll.empty())//空的显然有解 { cout<<"Ordering is possible."<<endl; } else if (in[ll.front()] - out[ll.front()] == 1 and out[ll.back()] - in[ll.back()] == 1) //出入度差为一且只有一个有节 { cout<<"Ordering is possible."<<endl; } else if (out[ll.front()] - in[ll.front()] == 1 and in[ll.back()] - out[ll.back()] == 1) //同上 { cout<<"Ordering is possible."<<endl; } else cout<<"The door cannot be opened."<<endl;//不然则无解 } return 0; } ``` 期末考前发题解rp++awa