POJ 2513 Colored Sticks(欧拉回路判断+字典树Trie+并查集)
原创
©著作权归作者所有:来自51CTO博客作者mb5f5b1df7f1e34的原创作品,请联系作者获取转载授权,否则将追究法律责任
Colored Sticks 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 Hint Huge input,scanf is recommended. Source The UofA Local 2000.10.14 |
Time Limit: 5000MS |
| Memory Limit: 128000K |
Total Submissions: 40272 |
| Accepted: 10463 |
题意:
给一些木棒,木棒两端都涂上颜色,求是否能将木棒首尾相接,连成一条直线,要求不同木棒相接的一边必须是相同颜色的
分析:
典型的判断欧拉路和欧拉回路问题,关键映射map竟然超时,用字典树就过来
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
using namespace std;
const int N=260000;
int n, m;
int f[N*2],degree[N*2];//记录第i点的度数
const int maxnode=5000000+1000;
const int sigma_size=26;
int cnt;//记录当前已经读入了cnt个不同的颜色了
struct Trie
{
int ch[maxnode][sigma_size];
int val[maxnode];//单词节点的val才非0,且val[i]表示的是该单词节点的编号
int sz;
void init()
{
sz=1;
memset(ch[0],0,sizeof(ch[0]));
val[0]=0;
}
int insert(char *s)
{
int n=strlen(s),u=0;
for(int i=0;i<n;i++)
{
int id=s[i]-'a';
if(ch[u][id]==0)
{
ch[u][id]=sz;
val[sz]=0;
memset(ch[sz],0,sizeof(ch[sz]));
sz++;
}
u=ch[u][id];
}
if(val[u]==0)//新颜色
val[u]=++cnt;
return val[u];
}
}trie;
int find_(int x)
{
if(f[x]==-1) return x;
return f[x] = find_(f[x]);
}
void merge_(int x, int y)
{
int t1, t2;
//cout<<f[x]<<endl;
t1 = find_(x);
t2 = find_(y);
if (t1 != t2) f[t2] = t1;
else return;
}
int isEuler()
{
int cnt=0;
for (int i = 1; i <= n; i++)
{
if (degree[i] & 1)
cnt++;
if(cnt>2) return 0;
}
if(cnt==2||cnt==0) return 1;
return 0;
}
int isconnect()
{
int cnt = 0;
int ff=find_(1);
for (int i=2; i <= n; i++)
{
if (find_(i)!=ff)
return 0;
}
return 1;
}
int main()
{
memset(f,-1,sizeof(f));
memset(degree, 0, sizeof(degree));
cnt=0;
trie.init();
char t1[100],t2[100];
n=1;
//int i=0;
while(scanf("%s%s",t1,t2)!=EOF)
{
int i=trie.insert(t1);//尝试插入新颜色
int j=trie.insert(t2);
//cout<<mapp[t1]<<" "<<mapp[t2]<<endl;
degree[i]++;
degree[j]++;
merge_(i,j);
//i++;
//if(i==5) break;
}
n=cnt;
//cout<<"sss"<<endl;
if(isconnect()&&isEuler())
printf("Possible");
else
printf("Impossible");
return 0;
}