UVA10129 POJ1386 HDU1116 ZOJ2016 Play on Words【欧拉回路+并查集】

来源:互联网 发布:贝勒医学院 知乎 编辑:程序博客网 时间:2024/06/10 03:18

问题链接:UVA10129 POJ1386 HDU1116 ZOJ2016 Play on Words

问题简述:先输入测试用例数T,每个测试用例包括整数N和N个单词数,问这些单词首尾字母能否接成一条龙?

问题分析:这是一个单词接龙问题,一个单词的尾字母和另外一个单词的首字母相同则可以接成龙。其中,每个单词只包含小写字母。单词的首字母和尾字母可以作为图的一个结点,从单词的首字母到尾字母画一条有向边,单词接龙问题就变成一笔画问题,或称为欧拉路径问题。

欧拉路径问题有两个条件,一是图是联通的;二是所有结点出入度相同,或者只有两个结点出入度差为1。

程序说明:用并查集来判定图是否是联通的。

程序提交后,除了POJ1386出现TLE,其他3个在线评判都AC了。在高人指点之下,程序中增加了69行的代码“ios::sync_with_stdio(false);”,就都可以通过了。这是由于C++的输入输出比较慢的原因,通过这行代码,改善了I/O的速度。

这个语句也可以写为“std::ios::sync_with_stdio(false);”。担心C++输入输出慢,可以使用该语句改善速度。


AC的C++语言程序如下:

/* UVA10129 Play on Words */#include <iostream>#include <string>#include <cstring>using namespace std;const int N = 26;// 并查集类int v[N];class UF {private:    int length;public:    UF(int n) {        length = n;        for(int i=0; i<=n; i++)            v[i] = i;    }    // 压缩    int Find(int x) {        if(x == v[x])            return x;        else            return v[x] = Find(v[x]);    }    bool Union(int x, int y) {        x = Find(x);        y = Find(y);        if(x == y) {            return false;        } else {            v[x] = y;            return true;        }    }};int degreeout[N];int degreein[N];// 出入度检查:return nopathflagbool degreeincheck(){    int startcount = 0, endcount = 0;    for(int i=0; i<N; i++)        if(degreeout[i] != degreein[i]) {            if((degreeout[i] - degreein[i]) == 1) {                if(++startcount > 1)                    return true;            } else if((degreeout[i] - degreein[i]) == -1) {                if(++endcount > 1)                    return true;            } else                return true;        }    return false;}int main(){    int t, n, src, dest;    ios::sync_with_stdio(false);    cin >> t;    while(t--) {        UF uf(N+1);        memset(degreeout, 0, sizeof(degreeout));        memset(degreein, 0, sizeof(degreein));        // 输入测试用例的数据,构建并查集,统计各个结点的度        cin >> n;        string s;        while(n--) {            cin >> s;            src = s[0] - 'a';            dest = s[s.size() - 1] - 'a';            degreeout[src]++;            degreein[dest]++;            uf.Union(src, dest);        }        // 判断图的联通性        bool nopathflag = false;        int root = -1;        for(int i=0; i<N; i++) {            if(degreeout[i] || degreein[i]) {                if(root == -1)                    root = uf.Find(i);                else if(uf.Find(i) != root) {                    nopathflag = true;                    break;                }            }        }        // 判定是否存在欧拉路径:出入度检查        if(!nopathflag)            nopathflag = degreeincheck();        // 输出结果        if(nopathflag)            cout << "The door cannot be opened." << endl;        else            cout << "Ordering is possible." << endl;    }    return 0;}


1 0
原创粉丝点击