https://vjudge.net/problem/UVA-10129
来 我们来学习一下欧拉路
欧拉路分为欧拉回路与欧拉道路
如果图G中的一个路径包括每个边恰好一次,则该路径称为欧拉道路
如果一个回路是欧拉道路 那么这个回路就是欧拉回路
具有欧拉回路的图称为欧拉图 有欧拉路径但是没有欧拉回路的称为半欧拉图
无向图判欧拉路
所有点度都是偶数,或者恰好有两个点度是奇数,则有欧拉路。
若有奇数点度,则奇数点度点一定是欧拉路的起点和终点(道路),否则可取任意一点作为起点。(回路)
有向图判欧拉路
- 每个点的入度等于出度,则存在欧拉回路(任意一点有度的点都可以作为起点)
- 除两点外,所有入度等于出度。这两点中一点的出度比入度大,另一点的出度比入度小,则存在欧拉路。取出度大者为起点,入度大者为终点。
这个题是求欧拉路径 而且这算是一个有向图 把每个单词的首字母和尾字母看成点 字母看成边 先判断出度不等于入度的点有几个 之后在用dfs爆搜一下是否连通
还可以用并查集写这个题 明天更新这方面的东西吧
#include <set>
#include<iostream>
#include <cstdio>
#include <algorithm>
#include<string>
#include<cstring>
using namespace std;
const int maxn = 105;
int vis[maxn],in[maxn], out[maxn];
int G[maxn][maxn];
int n, t;
void dfs(int u) {
vis[u] = true;
for (int i = 0; i < maxn; i++) {
if (G[u][i] && !vis[i])
dfs(i);
}
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cin >> t;
while (t--) {
memset(G, 0, sizeof(G));
memset(in, 0, sizeof(in));
memset(out, 0, sizeof(out));
char str[1005];
cin >> n;
for (int i = 0; i < n; i++) {
cin >> str;
G[str[0] - 'a'][str[strlen(str) - 1] - 'a']++;//只存第一个字母和最后一个字母
in[str[strlen(str) - 1] - 'a']++;
out[str[0] - 'a']++;
}
bool flag = true;
int num1 = 0;
int num2 = 0;
int tm = 0;
for (int i = 0; i < maxn; i++) {
if (!flag) break;
if (in[i] != out[i]) {//如果这个字母的出度不等于入度
if (in[i] == out[i] + 1) {//入度等于出度加一 说明这个点是终点
num1++;
}
else if (out[i] == in[i] + 1) {//起点
num2++;
tm = i;
}
else {
flag = false;
break;
}
}
}
if (num1 + num2 > 2) flag = false;//入度和出度不等的点的个数大于2
//接下来我们要确定这个图是否连通 不连通的话就不行
if (flag) {
memset(vis, 0, sizeof(vis));
dfs(tm);
bool flag2 = 1;
for (int i = 0; i < maxn; i++) {
if (in[i] && !vis[i]) {//有入度但是没有访问
flag2 = false;
break;
}
if (out[i] && !vis[i]) {
flag2 = false;
break;
}
}
if (flag2) {
cout << "Ordering is possible.\n";
}
else {
cout << "The door cannot be opened.\n";
}
}
else {
cout << "The door cannot be opened.\n";
}
}
return 0;
}







Comments | NOTHING