UVa 10129 Play on Words


好久不写代码果然手会生成屎

题目在poj上也有


题意就是给你一堆单词,按首位顺序排列起来,问你有没有解。

第一眼看上去是个哈密顿通路,单词当做节点,首尾关系作边,听上去妥妥的不过N有100000 复杂度太恐怖。

其实是从刘汝佳的小白书第二版(其实该叫小紫红书了)上欧拉回路那节看到的,所以得考虑考虑转换

把单词当边,首尾字符当做点 题目就转变为 欧拉通路


不得不感慨,图论算法的重点还是在构图!!!


判断欧拉通路:

1. 一个有向图存在欧拉回路必定也存在欧拉通路...因为通路的定义包括了回路
2. 不考虑为欧拉回路的情况..一个有向图是欧拉通路就必须有一个点出度-入度=1,一个点入度-出度=1..这两点就是欧拉通路的起点和终点..并且该图连通

3. 我自己加一条,其实是对2的理解:入读-出度>1 时直接return false ,排除 a->b a->c 这种情况


判断欧拉回路:

无向图是欧拉图的充要条件是所有点的度为偶数并且所有点联通
有向图是欧拉图的充要条件是所有点的入度=出度..并且联通...


判断连通

1. dfs遍历,这里有一份参考代码不过我一直怀疑其正确性。因为你无法确定有向图的起点,比如 a->b->c 如果你从b点开始搜的话就会悲催,但是你不知道b点上面还有没有点。

2. 并查集,并查集的方便之处不用废话。但是在图论中两点之间有多条边时需要注意一些细节的处理。


关于判断入读出度

一种办法是分别记录 in[] out[]

我用的办法是一个数组:sz[x]++ 表示拉出一条边,sz[x]--表示走来一条边,sz[x]==1 sz[x]==-1 就是上面的两种情况


上代码吧

这是只开sz[]的

#include <iostream>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#define N 101010
using namespace std;

int sz[333];
int fa[333];
bool ok[333];   //  数据中使用到的单词
int n, T;

int getfa(int v)
{
    if ( fa[v] == v ) return v;
    return fa[v] = getfa(fa[v]);
}

void init()
{
    memset(ok, 0, sizeof(ok));
    memset(sz, 0, sizeof(sz));
    cin >> n;
    string a;
    for ( int i('a'); i <= 'z'; i++) fa[i] = i;
    for ( int i(1); i <= n; i++)
    {
        cin >> a;
        int x = a[0], y = a[a.size() - 1];
        fa[getfa(x)] = getfa(y);
        ok[x] = ok[y] = true;
        sz[x]++;
        sz[y]--;
    }
}

bool check()
{
    int tf = 0 , i;
    for ( i = 'a'; i <= 'z'; i++)
    {
        if (ok[i])
        {
            if ( !tf ) tf = getfa(i);
            else if ( getfa(i) != tf ) return false;        //  不连通
        }
    }

    int c1 = 0, c2 = 0;
    for ( int i('a'); i <= 'z'; i++)
    {
        if (!ok[i]) continue;
        if ( sz[i] == 0 ) continue;
        else if ( sz[i] == 1 ) c1++;
        else if ( sz[i] == -1) c2++;
        else return false;				//  其它乱七八糟的情况 比如 ab ab out[a]=2 in[b]=2 
    }

    if ( (c1 == 1 && c2 == 1) || (c1 == 0 && c2 == 0) ) //  单向路径 or 回路
        return true;
    else
        return false;
}

int main()
{
    freopen("in.txt", "r", stdin);
    for ( cin >> T; T--; )
    {
        init();
        if (check())
            cout << "Ordering is possible." << endl;
        else
            cout << "The door cannot be opened." << endl;
    }
}


为保险起见,还是开了两个数组的

#include <iostream>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#define N 101010
using namespace std;

int in[333], out[333];
int fa[333];
bool ok[333];   //  数据中使用到的单词
int n, T;

int getfa(int v)
{
    if ( fa[v] == v ) return v;
    return fa[v] = getfa(fa[v]);
}

void init()
{
    memset(ok, 0, sizeof(ok));
    memset(in, 0, sizeof(in));
    memset(out, 0, sizeof(out));
    cin >> n;
    string a;
    for ( int i('a'); i <= 'z'; i++) fa[i] = i;
    for ( int i(1); i <= n; i++)
    {
        cin >> a;
        int x = a[0], y = a[a.size() - 1];
        fa[getfa(x)] = getfa(y);
        ok[x] = ok[y] = true;
        out[x]++;
        in[y]++;
    }
}

bool check()
{
    int tf = 0 , i;
    for ( i = 'a'; i <= 'z'; i++)
    {
        if (ok[i])
        {
            if ( !tf ) tf = getfa(i);
            else if ( getfa(i) != tf ) return false;        //  不连通
        }
    }

    int c1 = 0, c2 = 0;
    for ( int i('a'); i <= 'z'; i++)
    {
        if (!ok[i]) continue;
        if ( in[i] == out[i] ) continue;
        else if ( in[i] - out[i] == 1 ) c1++;
        else if ( in[i] - out[i] == -1) c2++;
        else return false;
        //else {printf("%d%d\n",in[i],out[i]);return false;}          //  其它乱七八糟的情况
    }

    if ( (c1 == 1 && c2 == 1) || (c1 == 0 && c2 == 0) ) //  单向路径 or 回路
        return true;
    else
        return false;
}

int main()
{
    //freopen("in.txt", "r", stdin);
    for ( cin >> T; T--; )
    {
        init();
        if (check())
            cout << "Ordering is possible." << endl;
        else
            cout << "The door cannot be opened." << endl;
    }
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
项目:使用 JavaScript 编写的杀死幽灵游戏(附源代码) 杀死鬼魂游戏是使用 Vanilla JavaScript、CSS 和 HTML 画布开发的简单项目。这款游戏很有趣。玩家必须触摸/杀死游荡的鬼魂才能得分。您必须将鼠标悬停在鬼魂上 - 尽量得分。鬼魂在眨眼间不断从一个地方移动到另一个地方。您必须在 1 分钟内尽可能多地杀死鬼魂。 游戏制作 这个游戏项目只是用 HTML 画布、CSS 和 JavaScript 编写的。说到这个游戏的特点,用户必须触摸/杀死游荡的幽灵才能得分。游戏会根据你杀死的幽灵数量来记录你的总分。你必须将鼠标悬停在幽灵上——尽量得分。你必须在 1 分钟内尽可能多地杀死幽灵。游戏还会显示最高排名分数,如果你成功击败它,该分数会在游戏结束屏幕上更新。 该游戏包含大量的 javascript 以确保游戏正常运行。 如何运行该项目? 要运行此游戏,您不需要任何类型的本地服务器,但需要浏览器。我们建议您使用现代浏览器,如 Google Chrome 和 Mozilla Firefox。要玩游戏,首先,单击 index.html 文件在浏览器中打开游戏。 演示: 该项目为国外大神项目,可以作为毕业设计的项目,也可以作为大作业项目,不用担心代码重复,设计重复等,如果需要对项目进行修改,需要具备一定基础知识。 注意:如果装有360等杀毒软件,可能会出现误报的情况,源码本身并无病毒,使用源码时可以关闭360,或者添加信任。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值