poj 2513解题报告
2013-08-29 18:25
337 查看
题目来源:http://poj.org/problem?id=2513
题目大意:
给你n根木棒,每个木棒两端都涂有颜色,任意两根木棒可以连在一起,如果他们有一端颜色是相同的,问你最后是否能把所有的木棒连成一根。
题目分析:
这道题是一个欧拉通路的判断,但是令人纠结的是,节点不是整数而是字符串,很头疼啊= =
如果不了解欧拉通路可以自己百度一下。。
因为节点是字符串,所以我们要把它转换成整数的节点,这就涉及到字符串的查找,但是map在这题是会超时的。。。所以想到可以用AC自动机
代码实现:
题目大意:
给你n根木棒,每个木棒两端都涂有颜色,任意两根木棒可以连在一起,如果他们有一端颜色是相同的,问你最后是否能把所有的木棒连成一根。
题目分析:
这道题是一个欧拉通路的判断,但是令人纠结的是,节点不是整数而是字符串,很头疼啊= =
如果不了解欧拉通路可以自己百度一下。。
因为节点是字符串,所以我们要把它转换成整数的节点,这就涉及到字符串的查找,但是map在这题是会超时的。。。所以想到可以用AC自动机
代码实现:
#include <cstdio> #include <cstring> using namespace std; typedef char char_t;//字符的类型,需要的话可以改成int等 const int SIGMA=26;//字符集的大小 const int ELEMENT_MAX=5000100;//trie图中最多可能的节点数,用于内存管理 #define MAX 500010 int father[MAX],rank[MAX]; int ID; char s1[MAX/2][15],s2[MAX/2][15]; int d[MAX]; int degree[MAX]; bool vis[MAX]; int len1[MAX/2],len2[MAX/2]; struct TrieGraph { struct trie { bool match; int id; trie *pre,*child[SIGMA]; trie():match(false),pre(0) { memset(child,0,sizeof(child)); id = -1; } void* operator new(size_t, void *p) { return p; } } root,superroot; static char storage[ELEMENT_MAX*sizeof(trie)]; static trie* data; static void init() { data=(trie*)storage; } void insert(char_t* s,int n) //在trie中插入一个长度为n的字符串s { //如果需要在trie节点中记录某些信息,一般是在这个函数里添加 trie* t=&root; for(int i=0; i<n; ++i) { char_t c=s[i]; if(!t->child[c]) { t->child[c]=new((void*)data++) trie; if(i == n-1) { ID++; } } t=t->child[c]; } if(!t->match) { t->match=true; t->id = ID; } } void build_graph() //所有的插入完毕后,将trie树扩充为图 { static trie* Q[ELEMENT_MAX]; superroot.pre=root.pre=&superroot; for(int i=0; i<SIGMA; ++i) superroot.child[i]=&root; int head=0,tail=0; Q[tail++]=&root; while(head!=tail) { trie* t=Q[head++]; t->match|=t->pre->match; for(int i=0; i<SIGMA; ++i) { if(t->child[i]) { t->child[i]->pre=t->pre->child[i]; Q[tail++]=t->child[i]; } else t->child[i]=t->pre->child[i]; } } } int match(char_t* s,int n) //返回长度为n的字符串s中有否已被插入的字符串的匹配 { trie* t=&root; for(int i=0; i<n; ++i) { t=t->child[s[i]]; } return t->id; } }; char TrieGraph::storage[ELEMENT_MAX*sizeof(trie)]; TrieGraph::trie* TrieGraph::data; void make_set() { int i; for(int i=1; i<=MAX/2; i++) { rank[i] = 0; father[i] = i; } } int find_set(int x) { if(x != father[x]) { father[x] = find_set(father[x]); } return father[x]; } void union_set(int x,int y) { x = find_set(x); y = find_set(y); if(rank[x] > rank[y]) father[y] = x; else { father[x] = y; if(rank[x] == rank[y]) { rank[y]++; } } } int main() { TrieGraph::init(); TrieGraph g; ID = 0; int k=0; int cnt = 0; memset(degree,0,sizeof(degree)); memset(vis,0,sizeof(vis)); make_set(); while(scanf("%s %s",s1[k],s2[k]) != EOF) { //printf("%s %s\n",s1[k],s2[k]); len1[k]=strlen(s1[k]); for(int i=0; i<len1[k]; ++i) s1[k][i]-='a'; g.insert(s1[k],len1[k]); len2[k]=strlen(s2[k]); for(int i=0; i<len2[k]; ++i) s2[k][i]-='a'; g.insert(s2[k],len2[k]); k++; } g.build_graph(); int ii=0; for(int i=0; i<k; ++i) { //printf("%d %d\n",len1[i],len2[i]); int d1 = g.match(s1[i],len1[i]); int d2 = g.match(s2[i],len2[i]); if(!vis[d1]) { d[ii++] = d1; vis[d1] = true; } if(!vis[d2]) { d[ii++] = d2; vis[d2] = true; } degree[d1]++; degree[d2]++; union_set(d1,d2); } for(int i=0; i<ii; i++) { if(degree[d[i]] % 2 == 1) cnt++; } memset(vis,false,sizeof(vis)); int ans = 0; if(cnt==1 || cnt >= 3) { printf("Impossible\n"); } else { int fanum=0; for(int i=0; i<ii; i++) { int fa = find_set(d[i]); //printf("%d %d\n",d[i],fa); if(!vis[fa]) { vis[fa] = true; ans++; } } if(ans > 1) printf("Impossible\n"); else printf("Possible\n"); } return 0; }
相关文章推荐
- POJ2513解题报告
- POJ - 2513 Colored Sticks解题报告(欧拉回路+并查集+字典树)
- POJ 2513 Colored Sticks (Trie字典树+欧拉通路+并查集) 解题报告
- POJ 2513 Colored Sticks 解题报告
- POJ 2513 解题报告
- poj1469 COURSES(匈牙利算法)(解题报告)
- 解题报告:POJ_1338 Ugly Numbers
- poj 2367 Genealogical tree 拓扑排序 解题报告
- POJ1450解题报告
- POJ-2002 Squares解题报告
- poj(百练) 2974 解题报告
- POJ2388解题报告
- POJ2229 解题报告
- 2011.11.10 poj1062,poj2253,poj1125 单源最短路径 解题报告
- POJ2139 解题报告
- 解题报告 之 POJ1087 A Plug for UNIX
- POJ 1477 解题报告
- POJ 2376 解题报告
- 再谈poj2255_解题报告
- POJ 3278 解题报告