poj 2513 Colored Sticks (trie树+并查集+欧拉路)
Colored Sticks
Time Limit: 5000MS | Memory Limit: 128000K | |
Total Submissions: 40043 | Accepted: 10406 |
Description
You are given a bunch of wooden sticks. Each endpoint of each stick is colored with some color. Is it possible to align the sticks in a straight line such that the colors of the endpoints that touch are of the same color?
Input
Input is a sequence of lines, each line contains two words, separated by spaces, giving the colors of the endpoints of one stick. A word is a sequence of lowercase letters no longer than 10 characters. There is no more than 250000 sticks.
Output
If the sticks can be aligned in the desired way, output a single line saying Possible, otherwise output Impossible.
Sample Input
blue red red violet cyan blue blue magenta magenta cyan
Sample Output
Possible
Hint
Huge input,scanf is recommended.
题目大意:
给定n根木棒,首尾各有一种颜色。求问有没有可能,将这些木棒连成一排,使得接头处颜色相同。
判断无向图是否存在欧拉路经典题。
一根木棒其实就是给两种颜色连上一条无向边(可能会有重边的)。那么一条欧拉路就相当于一种连接方式。
无向图存在欧拉图的条件:
1)联通。这个交给并查集就好了。
2)度数为奇数的点只能是0个或2个。这个建图的时候或建完图后都挺好处理的。
主要是如何建图呢。字符串太多了,要hash成数。用字典树比较合适。
每次遇见一种颜色,看字典树中有没有该颜色。如果有,返回该颜色的id,否则加入该颜色,id取全局变量++col。
#include<cstdio> #include<algorithm> #include<cstring> #include<queue> #include<stack> #include<deque> typedef long long ll; const int maxn=250000; int col; struct ttrie { bool isword; int id; ttrie* next[26]; ttrie() { isword=false; for(int i=0;i<26;i++) next[i]=NULL; } }; char str1[15],str2[15]; int add(ttrie* root,char str[]) { ttrie *p=root,*q; for(int i=0;str[i]!='\0';i++) { int temp=str[i]-'a'; if(p->next[temp]==NULL) { q=new ttrie; p->next[temp]=q; p=q; } else p=p->next[temp]; } if(p->isword) return p->id; else { p->isword=true; p->id=++col; return p->id; } } int degree[maxn*2+5]; int cnt; struct tedge { int u,v; }; tedge edge[maxn+5]; int fa[maxn*2+5]; int getfa(int x) { if(fa[x]==x) return x; else return fa[x]=getfa(fa[x]); } int main() { col=0; ttrie* root=new ttrie; memset(degree,0,sizeof(degree)); cnt=0; while(scanf("%s%s",str1,str2)!=EOF) { int u=add(root,str1); int v=add(root,str2); degree[u]++; degree[v]++; edge[++cnt]=(tedge){u,v}; } bool flag=true; for(int i=1;i<=col;i++) fa[i]=i; int tot=col; for(int i=1;i<=cnt;i++) { int fx=getfa(edge[i].u); int fy=getfa(edge[i].v); if(fx!=fy) { fa[fx]=fy; tot--; } } if(tot>1) flag=false; if(flag) { int odd=0; for(int i=1;i<=col;i++) { if(degree[i]%2) odd++; } if(odd!=0&&odd!=2) flag=false; } if(flag) printf("Possible\n"); else printf("Impossible\n"); return 0; }