题目描述
瑞瑞有一堆的玩具木棍,每根木棍的两端分别被染上了某种颜色,现在他突然有了一个想法,想要把这些木棍连在一起拼成一条线,并且使得木棍与木棍相接触的两端颜色都是相同的,给出每根木棍两端的颜色,请问是否存在满足要求的排列方式。
例如,如果只有 2 根木棍,第一根两端的颜色分别为 red, blue,第二根两端的颜色分别为 red, yellow,那么 blue—red | red----yellow 便是一种满足要求的排列方式。
输入格式
输入有若干行,每行包括两个单词,表示一根木棍两端的颜色,单词由小写字母组成,且单词长度不会超过 1010 个字母,最多有 250000250000 根木棍。
输出格式
如果木棒能够按要求排列,输出 Possible,否则输出 Impossible
输入输出样例
输入 #1复制
blue red
red violet
cyan blue
blue magenta
magenta cyan
输出 #1复制
Possible
上代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<map>
#include<cstring>
using namespace std;
#define xx 1000010
char s1[51],s2[50];
int tot=0,tot_v=1,k,ta=0;
//tot记录点数 ,k记录出度为奇数的点的个数。
int exist[xx],sum=0;
//这两个用于判断是否只有一个树。
struct er
{
int hash;
int next[27];
}a[800001];
struct re
{
int t,next,head,s,out,in;
}e[xx*4];
int search(char s[50])//hash字典树
{
int l = strlen(s);
int p = 1;
for (int i = 1; i <= l; i++)
{
int x = s[i - 1] - 'a' + 1;
if (a[p].next[x] == 0)
{
tot_v++;
a[p].next[x] = tot_v;
}
p = a[p].next[x];
}
if (a[p].hash == 0)
a[p].hash = ++tot;
return a[p].hash;
}
void build(int x,int y)//建树
{
e[++ta].t=y;e[ta].s=x;
e[x].out++;e[y].in++;
e[ta].next=e[x].head;e[x].head=ta;
}
void dfs(int x)//遍历判断是否是一个树或森林。
{
for(int i=e[x].head;i;i=e[i].next)
{
if(exist[e[i].t]==0)
{
exist[e[i].t]=1;
++sum;//记录一个树中的点数,看是否等于tot。
dfs(e[i].t);
}
}
}
int main()
{
while(cin>>s1>>s2)
{
int x,y;
x=search(s1);//变字符为数字,方便记录。
y=search(s2);
build(x,y);build(y,x);
}
for(int i=1;i<=tot;++i)
{
if(e[i].out%2!=0)
++k;
}
dfs(1);
int u=0;
if(sum==tot)
u=0;
else u=1;
if(u==1)//如果是森林,则不联通。
{
cout<<"Impossible";
return 0;
}
if((k==2||k==0))
cout<<"Possible";
if(k!=2&&k!=0)
cout<<"Impossible";
return 0;
}