1 条题解

  • 0
    @ 2025-5-14 22:04:13

    算法思想

    统计度数:用哈希表或字典统计每个颜色顶点的度数(即出现的次数)。

    检查连通性:使用并查集(Disjoint Set Union, DSU)或深度优先搜索(DFS)检查图是否连通。

    检查度数条件:统计奇数度数的顶点数量,判断是否符合欧拉路径或欧拉回路的条件。

    代码实现

    
    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <map>
    #include <cstring>
    using namespace std;
    
    const int N = 250010 << 1;
    int p[N]; // 并查集
    int d[N]; // 度
    
    /*
    在这个代码中,我们定义了一个函数getHash来获取字符串的哈希值。
    这个函数使用了一种称为多项式滚动哈希的方法,它将字符串看作一个31进制的数,并将每个字符的ASCII值减去'a'的ASCII值
    加1作为该字符的值。然后,我们将每个字符的值乘以31的相应次方,并将结果加到哈希值上。
    为了防止哈希值溢出,我们在每一步都对哈希值取模N。
    */
    int getHash(string s) {
        int p = 31, b = 1, hash = 0;
        for (int i = 0; i < s.size(); i++) {
            hash = (hash + (s[i] - 'a' + 1) * b) % N;
            b = (b * p) % N;
        }
        return hash;
    }
    
    // 并查集
    int find(int x) {
        if (x == p[x]) return x;
        return p[x] = find(p[x]);
    }
    
    char str1[15], str2[15]; // 两个字符串
    int b[N];                // 判断某个字符串HASH值是不是已经出现过的桶
    
    int main() {
    #ifndef ONLINE_JUDGE
        freopen("POJ2513.in", "r", stdin);
    #endif
        // 初始化并查集
        for (int i = 0; i < N; i++) p[i] = i;
        // 离散化后的节点编号,是不是存在一笔画的标识
        int id = 0, flag = 1;
    
        while (~scanf("%s%s", str1, str2)) {
            int s1 = getHash(str1), s2 = getHash(str2); // 计算出个字符串的HASH值,而且,数值在N以下,这样才能用桶
            if (!b[s1]) b[s1] = ++id;                   // 给字符串编号,去重
            if (!b[s2]) b[s2] = ++id;                   // 给字符串编号,去重
            int x = b[s1], y = b[s2];                   // 去重+映射后的字符串编号
            d[x]++, d[y]++;                             // 记录度
            // 合并并查集
            if (find(x) != find(y)) p[find(x)] = find(y); // 辅助校验图是否是连通的
        }
    
        int odd = 0, cnt = 0;
        for (int i = 1; i <= id; i++) { // 枚举每个去重后的字符串
            if (p[i] == i) cnt++;       // 连通块个数
            if (d[i] % 2) odd++;        // 奇数度节点个数
        }
    
        // 如果奇数度个数不是0,而且,还不是2,那肯定不是一笔画
        // 如果连通块个数不是1,也不能一笔画
        if ((odd != 0 && odd != 2) || cnt != 1) flag = 0;
        // 空数据也需要处理,这太BT了!
        if (id == 0) flag = 1;
    
        if (flag)
            puts("Possible");
        else
            puts("Impossible");
        return 0;
    }
    
    
    
    • 1

    信息

    ID
    1514
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    2
    已通过
    1
    上传者