题意:给你n个单词(只有小写),要求这些单词首尾相连,问你这n个单词能不能全部连起来,可以连成一条链或者连成一个环。
思路:顶点集合就是26个小写字母,用0到25来表示,每个单词的首字母到尾字母就是一条有向边,因为单词是不能倒回来的。其实就是问你这个图是否存在欧拉道路(一条链的情况)或者欧拉回路(环的情况),反正存在欧拉路就是成功的,否则就是失败。
①有一个入度比出度大一的点&&有一个出度比入度大一的点或者所有点的入度和出度都相同
②图是连通的
注意string会超时。
DFS判连通:
//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
const int MAXN = 26 + 5;
int n, G[MAXN][MAXN], indegree[MAXN], outdegree[MAXN];
void init()
{
memset(G, 0, sizeof(G));
memset(indegree, 0, sizeof(indegree));
memset(outdegree, 0, sizeof(outdegree));
}
void dfs(int u)//判断图是否连通
{
for (int v = 0; v < 26; v++)
{
if (G[u][v])
{
G[u][v]--;
dfs(v);
}
}
}
bool judge()
{
int cnt1 = 0, cnt2 = 0, S = 0;
for (int i = 0; i < 26; i++)
{
if (indegree[i] - outdegree[i] == -1) S = i, cnt1++;
if (indegree[i] - outdegree[i] == 1) cnt2++;
if (abs(indegree[i] - outdegree[i]) > 1) return false;
}
if (!((cnt1 == 0 && cnt2 == 0) || (cnt1 == 1 && cnt2 == 1))) return false;
dfs(S);
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 T;
scanf("%d", &T);
while (T--)
{
init();
scanf("%d", &n);
for (int i = 0; i < n; i++)
{
/*string str; cin >> str;
int s = str.back()- 'a', e = str.front() - 'a';*/
char str[1005]; scanf("%s", str);
int u = str[0] - 'a', v = str[strlen(str) - 1] - 'a';
outdegree[u]++; indegree[v]++;
G[u][v]++;
}
if (judge()) printf("Ordering is possible.\n");
else printf("The door cannot be opened.\n");
}
return 0;
}
/*
3
2
acm
ibm
3
acm
malform
mouse
2
ok
ok
*/
并查集判连通:
//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
const int MAXN = 26 + 5;
int n, f[MAXN], indegree[MAXN], outdegree[MAXN];
void init()
{
memset(indegree, 0, sizeof(indegree));
memset(outdegree, 0, sizeof(outdegree));
for (int i = 0; i < MAXN; i++) f[i] = i;
}
int Find(int x) { return f[x] == x ? x : f[x] = Find(f[x]); }
void Union(int a, int b)
{
int root1 = Find(a), root2 = Find(b);
if (root1 != root2)
{
f[root1] = root2;
}
}
bool judge()
{
int cnt1 = 0, cnt2 = 0;
for (int i = 0; i < 26; i++)
{
if (indegree[i] - outdegree[i] == -1) cnt1++;
if (indegree[i] - outdegree[i] == 1) cnt2++;
if (abs(indegree[i] - outdegree[i]) > 1) return false;
}
if (!((cnt1 == 0 && cnt2 == 0) || (cnt1 == 1 && cnt2 == 1))) return false;
int cnt = 0;
for (int i = 0; i < 26; i++)
{
if ((outdegree[i] + indegree[i]) > 0 && f[i] == i)
{
cnt++;
}
}
if (cnt == 1) return true;
return false;
}
int main()
{
int T;
scanf("%d", &T);
while (T--)
{
init();
scanf("%d", &n);
for (int i = 0; i < n; i++)
{
char str[1005]; scanf("%s", str);
int u = str[0] - 'a', v = str[strlen(str) - 1] - 'a';
outdegree[u]++; indegree[v]++;
Union(u, v);
}
if (judge()) printf("Ordering is possible.\n");
else printf("The door cannot be opened.\n");
}
return 0;
}
/*
3
2
acm
ibm
3
acm
malform
mouse
2
ok
ok
*/