Time Limit: 5000MS | Memory Limit: 128000K | |
Total Submissions: 32788 | Accepted: 8639 |
Description
Input
Output
Sample Input
blue red red violet cyan blue blue magenta magenta cyan
Sample Output
Possible
题目大意: 判断已给的棍子是否可以调整成一条直线。(前提是相接的部分是同一颜色)
思路:若要使颜色有相同的,颜色数必须为偶数。分别用两段字符串建立Tire,利用标记变量分别在建树完成后返回该颜色的建树编号。
利用此编号来记录当前颜色出现的次数,与此同时,利用并查集,看是否是连通图。判断如果颜色出现的次数为一个奇数或奇数的个数>2者直接Impossible,
否则再判断连通性,如果有颜色的跟节点不是最开始的数(在里为1),也是Impossible,否则为possible
#include<iostream> #include<cstring> #include<cstdio> #include<queue> #include<algorithm> #define SUM 250001 #define LL long long #define inf 0x3f3f3f3f using namespace std; struct node { int flag; node *next[27]; } ; int f[500010],cnt,s,du[500010]; char s1[16],s2[16],now[32]; node *init() { node *p; p=new node ; for(int i=0; i<26; i++) p->next[i]=NULL; p->flag=0; return p; } int bu(node *root,char *s1) { int x,l; l=strlen(s1); for(int i=0; i<l; i++) { x=s1[i]-'a'; if(!root->next[x]) { root->next[x]=init(); } root=root->next[x]; } if(root->flag) return root->flag; else { root->flag=++s; return s; } } int fi(int r) { return r==f[r]?r:f[r]=fi(f[r]); } void mer(int x,int y) { int a=fi(x); int b=fi(y); if(a>b) f[a]=b; else f[b]=a; } int main() { s=cnt=0; node *root; root=new node ; root=init(); memset(du,0,sizeof(du)); for(int i=1; i<=SUM; i++) f[i]=i; while(gets(now)!=NULL)//注意若是遇到这种输入的方式一定是gets()+sscanf()的形式 { if(!strcmp(now,"")) break; sscanf(now,"%s%s",s1,s2); int x=bu(root,s1); int y=bu(root,s2);//返回下标的形式,可以很好的描述du的状态,并进行连通图的判断 du[x]++; du[y]++; mer(x,y); } int tmp=0; for(int i=1; i<=s; i++) { if(du[i]%2) tmp++; if(tmp>2) break; } if(tmp%2||tmp>2)//如果是度==1||度>2则直接输出,不可能 { puts("Impossible"); return 0; } bool bj=false; for(int i=1;i<=s;i++) { if(f[i]!=1)//判断是不是连通图,即是否全图都是唯一的跟节点 { bj=true; break; } } if(bj) { puts("Impossible"); return 0; } else puts("Possible"); return 0; }