Colored Sticks
Time Limit: 5000MS | Memory Limit: 128000K | |
Total Submissions: 40197 | Accepted: 10445 |
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.
题意:
木棒首尾有颜色,问 根据木棒首尾的颜色,能不能把木棒连接成一根。
解题思路:
可以把不同的颜色,视为节点,木棒为边,建图。数据量很大,如果用map会超时。(so bad)。。
所以就借助字典树 实现 string->int的 转换
然后 看建的图是否存在欧拉路径即可
欧拉路径:1、是否连通(借用并查集)2、奇数度点个数 为0或者 2
总之:这道题收益颇多……嘻嘻
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <stack>
#include <queue>
#include <vector>
#include <map>
#include <algorithm>
#define ll long long
#define pi acos(-1.0)
#define inf 0x3f3f3f3f
#define Max 505555 //木棍有250000 则颜色最多 500000种
using namespace std;
int trie[Max][30];//数组形式定义字典树,值存储的是下一个字符的位置
int num[Max][30];//颜色的序号
int deg[Max];//颜色的度
int fa[Max];
int pos;//序号
int id;//颜色的编号
//并查集
void init()
{
pos=1;
id=1;
memset(trie,0,sizeof(trie));
memset(num,0,sizeof(num));
memset(deg,0,sizeof(deg));
for(int i=0;i<=Max;i++)
fa[i]=i;
}
int find(int x)
{
if(fa[x]==x) return x;
return fa[x]=find(fa[x]);
}
void join(int a,int b)
{
int Fa=find(a);
int Fb=find(b);
if(Fa!=Fb)
{
fa[Fa]=Fb;
}
}
//在字典树中插入某个颜色 ,并返回颜色的编号
int Insert(char s[])
{
int c=0;
for(int i=0;s[i];i++)
{
int n=s[i]-'a';
if(trie[c][n]==0) trie[c][n]=pos++;
c=trie[c][n];
}
if(num[c][s[strlen(s)-1]-'a']==0)//当前字母没有出现过
num[c][s[strlen(s)-1]-'a']=id++;
return num[c][s[strlen(s)-1]-'a'];
}
int main(){
// ios::sync_with_stdio(false);
init();
char s1[101],s2[101];
while(scanf("%s%s",s1,s2)!=EOF)
{
int p1=Insert(s1);
int p2=Insert(s2);
// cout<<"s1:"<<s1<<" id -> "<<p1<<endl;
// cout<<"s2:"<<s2<<" id -> "<<p2<<endl;
deg[p1]++;
deg[p2]++;
join(p1,p2);
}
// cout<<"*** id: "<<id-1<<endl;
int Fa_num=0;//父节点的个数
for(int i=1;i<id;i++)
{
// cout<<"***fa: "<<find(i)<<endl;
if(i==find(i)) Fa_num++;
if(Fa_num>=2) break;
}
// cout<<"***: "<<Fa_num<<endl;
if(Fa_num>=2) printf("Impossible\n");//不连通
else
{
int deg_num=0;//奇度点的个数
for(int i=1;i<=id;i++)
{
if(deg[i]%2) deg_num++;
}
if(deg_num==0||deg_num==2) printf("Possible\n");
else printf("Impossible\n");
}
return 0;
}