poj-2513

题意大概是,让你每次输入两个颜色单词,表示这是连成一条木棍的单词(从这可以看出这是一个无向图,因为无前后关系),然后他要求说能否根据这个拼接成一条路线,把所有的木棍都应连接,把木棍看成边,单词看成点,就是要让你把所有的边都连一遍,当然是不重复也不漏的,这恰好是无向图欧拉通路的问题。因此要保证图是连通的,而且奇数点的个数要么是0要么是2.

这里判断图的连通用并查集(压缩路径),即看看最后是不是在同一个集合里面,而每个点的度的问题比较简单,难点在于如何表示这个点的状态,这里我们用字典树,然后用全局变量color记录当前已经出现的颜色的个数,返回这个数字表示这个状态(单词)。

这里用字典树的好处在哪?这里相当于用内存换时间的方法。所以搜索只要O(1)时间。假如不用字典树的话,那你每次都要遍历所有的单词。

 
 
 
 
#include<cstdio>
#include<iostream>
#include<string.h>
using namespace std;
#define MAXN 500010
struct trieTreeNode{
	int id;
	struct trieTreeNode* next[27];
	bool flag;
	trieTreeNode()
	{
		flag=false;
		id=0;
		memset(next,0,sizeof(next));
	}
}root;
int color=0;
int p[MAXN],degree[MAXN];
int find(int x)
{
	if(p[x]!=x)
		p[x]=find(p[x]);
	return p[x];
}
void Union(int a,int b)
{
	int x1=find(a);
	int x2=find(b);
	if(x1!=x2)
		p[x1]=x2;
	return ;
}
int hash(char *str)
{
	struct trieTreeNode* ptr=&root;
	int len=0;
	while(str[len]!='\0'){
		int index=str[len++]-'a';
		if(!ptr->next[index]){
			ptr->next[index]= new trieTreeNode;
		}
		ptr=ptr->next[index];
	}
	if(ptr->flag==1){
		return ptr->id;
	}
	else{
		ptr->flag=true;
		ptr->id=color++;
		return ptr->id;
	}
}
int main()
{
	//initial
	for(int i=0;i<MAXN;i++)
		{
			p[i]=i;
			degree[i]=0;
		}
	char str1[11],str2[11];
	int count=0;
	while(cin>>str1>>str2){
		int a,b;
		a=hash(str1);
		b=hash(str2);
		degree[a]++;degree[b]++;
		Union(a,b);
	}
	int s=find(0),num=0,yes=1;//num统计奇数节点的个数 
	for(int i=0;i<color;i++)
	{
		if(degree[i]%2==1)num++;
		if(find(i)!=s)yes=0;
	}
	if(num!=0 && num!=2)yes=0;
	if(yes)cout<<"Possible"<<endl;
	else cout<<"Impossible"<<endl;
	return 0;
 } 





猜你喜欢

转载自blog.csdn.net/qq_35930475/article/details/79207131