给你250000个棒子,棒子两头有颜色,问你可不可以用完所有的棒子,把棒子连起来,并且使得棒子相连的两头颜色一样。
其实就是求欧拉回路。
有无向图存在欧拉路的充要条件为:
1->图是连通的;
2->所有节点的度为偶数,或者有且只有两个度为奇数的节点。
判断图的连通性,用并查集搞定。又题目给的棒子颜色是字符串,所以要用trie树把每个颜色的编号记录下来。
注意,这里用map会超时。。因为map基于hash,并不高效,所以这里需要用trie树来处理。。
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> using namespace std; #define MAX 260000 int uset[MAX],degree[26000]; int BCG_root(int k) { if(k==uset[k])return k; return uset[k]=BCG_root(uset[k]); } int BCG_init() { for(int i=0;i<MAX;++i) uset[i]=i; return 0; } struct node { int flag; //如果是终止状态,则标记是哪个字符 int tag; int next[26]; int init() { memset(next,-1,sizeof(next)); flag=0; tag=0; return 0; } }trie[260000]; int size=1; const int root=0; int val(char a) { return a-'a'; } int insert(char* s,int k) { int p=root; for(int i=0;s[i];++i) { int v=val(s[i]); if(trie[p].next[v]==-1) { trie[p].next[v]=size; trie[size].init(); ++size; } p=trie[p].next[v]; } trie[p].tag=1; trie[p].flag=k; return 0; } int match(char* s) { int p=root; for(int i=0;s[i];++i) { int v=val(s[i]); p=trie[p].next[v]; if(trie[p].tag) return trie[p].flag; } return 0; } void init() { size=1; trie[root].init(); return ; } int main() { char str[15]; int n,cnt,i,j,anc,sum,t1,t2; init(); BCG_init(); cnt=1; memset(degree,0,sizeof(degree)); while (scanf("%s",str) != EOF) // for (int k=0; k<5; k++) { // scanf("%s",str); j=match(str); if (j == 0) { insert(str,cnt); degree[cnt]++; t1=cnt; cnt++; } else { degree[j]++; t1=j; } scanf("%s",str); j=match(str); if (j == 0) { insert(str,cnt); degree[cnt]++; t2=cnt; cnt++; } else { degree[j]++; t2=j; } uset[BCG_root(t1)]=BCG_root(t2); } anc=BCG_root(1); sum=0; // printf("anc=%d\n",anc); for (i=1; i<cnt; i++) { // printf("%d\n",i); // printf("%d\n",BCG_root(i)); // printf("!!\n"); if (BCG_root(i) != anc) { // printf("@"); break; } if (degree[i]%2 == 1) sum++; } if (i != cnt || (sum != 2 && sum != 0)) printf("Impossible\n"); else printf("Possible\n"); }