UVa 10129 & HDU 1116 & POJ 1386 - Play on Words

35 篇文章 0 订阅
25 篇文章 0 订阅

传送门UVa 10129 & HDU 1116 & POJ 1386 - Play on Words


欧拉道路的题目。


题意是给你一串英文,让你判断能不能把它们连起来。

因为只需要判断首尾字母,所以只取它们就行。

思路是先判断起点和终点是不是符合要求,即至多有两个点的入度不等于出度,而且其中一个必须入度比出度大1,另一个入度比出度小1,即起点和终点。

如果符合上面那个要求,判断图是否连通就行。


本来昨天是要做这题的,当然是不会做,因为看到了欧拉道路这个陌生的名字。

于是我又回去翻了一下小白书,发现还有两道例题我没看完。。怪不得。

搜索了一下解题报告,可以用DFS,也可以用并查集来做。。后者我还没接触到,不明觉厉。

一开始参考了@shuangde800的解题报告。第一次放UVa上,AC了。然后我看了一下程序,他的数组开到了G[100][100],实际上只要够26个英文字母就行了。然后我就改成了30,WA了。我就知道这代码有问题,但还是不能确定。在到HDU上提交了一下,WA,在POJ上,WA。所以我就开始找错了。。。

找了大概半小时,又看了几份解题报告,直到看到了@Yoangh的一句话:

//因为是有向图,如果不是欧拉回路的情况,随便找个点为起点dfs不一定能遍历所有点,如3 a b b c c d只能以a为起点否则就会判断连通性错误

然后思路就连起来了。原来是找起点这里有问题。


修过了一下,AC。

详情见代码


#include <cstdio>
#include <cstring>
using namespace std;

const int MAXN = 30;
int graph[MAXN][MAXN];
int vis[MAXN];
int in[MAXN], out[MAXN];

void DFS(int n);

int main()
{
    //freopen("input.txt", "r", stdin);
    int T, n, i, j, target, start, num;
    char str[1005];
    scanf("%d", &T);
    while (T--)
    {
        target = start = 0;
        memset(graph, 0, sizeof(graph));
        memset(vis, 0, sizeof(vis));
        memset(in, 0, sizeof(in));
        memset(out, 0, sizeof(out));
        scanf("%d%*c", &n);
        for (i = 0; i < n; i++)
        {
            scanf("%s%*c", str);
            graph[str[0] - 'a'][str[strlen(str) - 1] - 'a'] = 1;
            out[str[0] - 'a']++;
            in[str[strlen(str) - 1] - 'a']++;
            num = str[0] - 'a';
        }
        bool flag = true;   //这个标志用来判断是否满足度数的条件。
        //接下来判断至多有两个点,一个点入度比出度多一,另一个点相反,即起点和终点
        for (i = 0; i < MAXN; i++)
        {
            if (!flag)
                break;
            if (in[i] != out[i])
                if (in[i] == out[i] + 1)
                    target++;
                else if (in[i] + 1 == out[i])
                {
                    num = i;    //记录起点。
                    start++;
                }
                else
                    flag = false;
            if (target > 1 || start > 1)
                flag = false;
        }
        if (flag)   //如果满足上面那个条件,判断是否连通。
        {
            DFS(num);
            bool flag2 = true;
            for (i = 0; i < MAXN; i++)
            {
                if (in[i] && !vis[i] || out[i] && !vis[i])  //如果一个点有路,确没有在DFS中被访问到,说明是断的。
                {
                    flag2 = false;
                    break;
                }
            }
            if (flag2)
                printf("Ordering is possible.\n");
            else
                printf("The door cannot be opened.\n");
        }
        else
            printf("The door cannot be opened.\n");
    }
    return 0;
}

void DFS(int n)
{
    vis[n] = 1;
    for (int i = 0; i < MAXN; i++)
        if (graph[n][i] && !vis[i])
            DFS(i);
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值