自己的代码超时了。。。不应该啊,方法没错哦,明天检查一下吧,网上看到一份不错的代码,不是针对于该题目,而是打印中间过程的方法,很细致,非常有利于debug
#include <stdio.h> #include <string.h> //#define DEBUG #ifdef DEBUG #define debug(...) printf( __VA_ARGS__) #else #define debug(...) #endif #define M 530001 #define N 500001 struct trie_node { int color_id; /* 叶子节点存储颜色编号,从1开始 */ int child[26]; /* 分支节点,静态链表表示 */ }; struct trie_node trie_tree[M]; /* trie树的静态链表表示法,trie_tree[0]是树根 */ int current; /* Trie树当前使用了多少个节点 */ int parent[N]; /* 并查集树形表示,parent[u] = r,若r > 0,u的 父亲为r, 若r < 0, 则u是根节点,其高度为-r */ int degree[N]; int n; /*顶点个数, 即有多少种颜色 */ /* 把单词插入Trie树,如果单词已存在直接返回颜色编号, * 不存在则插入,同时返回新生成的颜色编号 */ int insert(char *color) { char *p; struct trie_node *node; int new_node; node = trie_tree; //沿着树根一直往下插 for (p = color; *p != '\0'; p++) { debug("开始插入 %c...\n", *p); if (node->child[*p-'a'] == 0) { debug("没有%c, 新建节点\n", *p); node->child[*p-'a'] = current++; } else { debug("存在%c\n", *p); } node = trie_tree + node->child[*p-'a']; } //到达记录统计单词次数的节点 if (node->color_id == 0) { node->color_id = ++n; } debug("%s插入完成,其编号为%d\n", color, node->color_id); return node->color_id; } /* 找i的根节点 */ int find(int i) { for(; parent[i] > 0; i = parent[i]) ; return i; } void merge(int x,int y) { int px, py; px = find(x); py = find(y); if (px == py) return; debug("%d的树根为%d,树高=%d,%d的树根为%d, 树高=%d\n", x, px, -parent[px], y, py, -parent[py]); if (parent[px] < parent[py]) { /* x所在的树比y所在的树要高 */ parent[py] = px; debug("合并后树根为%d, 高度=%d\n", px, -parent[px]); } else if (parent[px] > parent[py]) { /* x所在的树比y所在的树要矮 */ parent[px] = py; debug("合并后树根为%d, 高度=%d\n", py, -parent[py]); } else { parent[py] = px; parent[px]--; /* 树的高度加1 */ debug("合并后树根为%d, 高度=%d\n", px, -parent[px]); } } int main() { char color1[11], color2[11]; int u, v, subgraph, count; current = 1; n = 0; memset(parent, -1, sizeof(parent)); memset(degree, 0, sizeof(degree)); while (scanf("%s %s", color1, color2) != EOF) { u = insert(color1); v = insert(color2); degree[u]++; degree[v]++; merge(u, v); } //空数据打印Possible, 否则Wrong Answer if (n == 0) { printf("Possible\n"); return 0; } //计算奇数度顶点的个数 count = 0; for (u = 1; u <= n; u++) { if (degree[u]%2 != 0) { if(++count > 2) break; } } debug("奇数度的顶点个数为%d\n", count); /* 计算并查集有几个分支,只有一个分支,说明图是连通的, * 如果有两个或两个以上的分支,则图不是连通的 */ subgraph = 0; if (count == 0 || count == 2) { for (u = 1; u <= n; u++) { /* parent[u] < 0说明u是树根,有多少树根,并查集就有多少个分支 */ if (parent[u] < 0) { if (++subgraph > 1) { break; } } } if (subgraph == 1) { printf("Possible\n"); return 0; } } printf("Impossible\n"); return 0; }