POJ ~ 1386 ~ Play on Words (欧拉路)

本文介绍了一种利用图论中的欧拉路径概念来解决单词链问题的方法,通过构建有向图,判断是否存在从一个单词开始,首尾相连形成链或环的可能性。文中提供了两种实现方案,一种使用深度优先搜索(DFS)判断连通性,另一种采用并查集实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:给你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
*/





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值