题意:有最多250000个木棍,木棍每端有一个颜色(不超过10个字符),两端颜色相同可以挨着排放,问能否将这些木棍排成一排。
思路:一开始自己写的用数组存颜色字符串,结果不够存。后来看到AC做法是用trie来存。于是写出用trie存的。一开始自己犯懒没仔细算trie结点的上限,看discuss有人说开500000不够,至少开510000,但奇怪的是我开510000都是RE。之后用GCC提交了一次AC了,然后在C下开到520000才能AC。后来算了一下结点上界数量,我认为不应该是颜色数量这个数:因为颜色最多500000个,又26^4=456976,所以结点上限应该为:1+26+26^2+26^3+26^4+500000*6=3475255个。后来用这个上限测了一下还是能AC的。
其次,判断连通用并查集也是一个比较自然的想法。以前我一直是将图存下然后深搜判断,但是这个结点上限开一个二维数组显然要RE。anyway,这道题还是比较综合。
#include <stdio.h> #include <string.h> #define N 3475256//gcc505000 c520000 typedef struct node{ int id; struct node * next[26]; }node; node *alloc,*root,array[N]; char s[12],t[12]; int f[N],d[N],top=0; void init(){ int i; memset(d, 0, sizeof(d)); for(i = 1;i<N;i++) f[i] = i; alloc = array; root = alloc++; root->id = 0; for(i = 0;i<26;i++) root->next[i] = NULL; } int find(char* x){ int i,j; node *p,*q; p = root; for(i = 0;x[i]!='\0';i++){ if(NULL == p->next[x[i]-'a']) break; p = p->next[x[i]-'a']; } if(x[i] == '\0' && p->id) return p->id; for(;x[i]!='\0';i++){ q = alloc++; q->id = 0; for(j = 0;j<26;j++) q->next[j] = NULL; p->next[x[i]-'a'] = q; p = q; } return p->id = ++top; } int unionfind(x){ if(f[x] == x) return x; return f[x] = unionfind(f[x]); } void merge(int x,int y){ int xx = unionfind(x); int yy = unionfind(y); if(xx != yy) f[xx] = yy; } int con(){ int i,res = unionfind(1); for(i = 2;i<=top;i++) if(unionfind(i) != res) return 0; return 1; } int main(){ int i,a,b,odd=0; init(); while(scanf("%s",s)!=EOF){ scanf("%s",t); a = find(s); b = find(t); d[a]++; d[b]++; merge(a,b); } if(!con()) printf("Impossible\n"); else{ for(i = 1;i<=top;i++) if(d[i] & 1) odd++; if(!odd || odd==2) printf("Possible\n"); else printf("Impossible\n"); } return 0; }