poj2513_trie_并查集_欧拉路
题意:给定一些木棒,木棒两端都涂上颜色,求是否能将木棒首尾相接,连成一条直线,要求不同木棒相接的一边必须是相同颜色的。
分析:
参考http://blog.csdn.net/lyy289065406/article/details/6647445
可以用图论中欧拉路的知识来解这道题,首先可以把木棒两端看成节点,把木棒看成边,这样相同的颜色就是同一个节点
问题便转化为:给定一个图,是否存在“一笔画”经过涂中每一点,以及经过每一边一次。这样就是求图中是否存在欧拉路Euler-Path。
由图论知识可以知道,无向图存在欧拉路的充要条件为:
① 图是连通的;
② 所有节点的度为偶数,或者有且只有两个度为奇数的节点。
图的连通性可以通过并查集来做,但是首先得hash到int型,但是使用map会超时。因此使用了trie树,这也是我第一次用trie来hash。所以这个题挺综合的。用到了三个知识呀。
代码:
View Code
1 #include <iostream> 2 #include <string.h> 3 #include <stdio.h> 4 using namespace std; 5 //79372K 1157MS 6 //trie+并查集+欧拉路径 7 const int maxnum=500010; 8 int degree[maxnum],parent[maxnum],rank[maxnum]; 9 int n=1; 10 struct node 11 { 12 int id; 13 bool use; 14 node *next[27]; 15 node() 16 { 17 id=0; 18 use=false; 19 int i; 20 for(i=0;i<27;i++) 21 next[i]=NULL; 22 } 23 }; 24 node *root; 25 26 int hash(char *str) 27 { 28 node *p=root; 29 int k; 30 while(*str!=0) 31 { 32 k=*str-'a'; 33 if(p->next[k]==NULL) 34 p->next[k]=new node(); 35 p=p->next[k]; 36 str++; 37 } 38 if(!p->use) 39 { 40 p->id=n; 41 n++; 42 p->use=true; 43 return p->id; 44 } 45 else 46 return p->id; 47 } 48 49 int find(int u) 50 { 51 if(u!=parent[u]) 52 parent[u]=find(parent[u]); 53 return parent[u]; 54 } 55 56 void Union(int i,int j) 57 { 58 if(rank[i]<rank[j]) 59 parent[i]=j; 60 else 61 { 62 parent[j]=i; 63 if(rank[i]==rank[j]) 64 i++; 65 } 66 } 67 68 int main() 69 { 70 char a[15],b[15]; 71 int i; 72 root=new node(); 73 for(i=1;i<maxnum;i++) 74 parent[i]=i; 75 while(scanf("%s%s",a,b)!=EOF) 76 { 77 int k=hash(a); 78 int l=hash(b); 79 degree[k]++; 80 degree[l]++; 81 82 int p=find(k); 83 int q=find(l); 84 if(p!=q) 85 Union(p,q); 86 } 87 int t=find(1); 88 int num=0; //度数为奇数的结点个数 89 for(i=1;i<n;i++) 90 { 91 if(find(i)!=t)//存在多个祖先,图为森林,不连通 92 { 93 printf("Impossible\n"); 94 return 0; 95 } 96 if(degree[i]%2==1) 97 num++; 98 if(num>2) //度数为奇数的结点数大于3,欧拉路必不存在 99 { 100 printf("Impossible\n"); 101 return 0; 102 } 103 } 104 if(num==1) //度数为奇数的结点数等于1,欧拉路必不存在 105 printf("Impossible\n"); 106 else //度数为奇数的结点数恰好等于2或不存在,存在欧拉路 107 printf("Possible\n"); 108 return 0; 109 } 110 111 /* 112 blue red 113 red violet 114 cyan blue 115 blue magenta 116 magenta cyan 117 */