poj2513(字典树)

 

Colored Sticks
Time Limit: 5000MS   Memory Limit: 128000K
Total Submissions: 27373   Accepted: 7240

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.

Source

The UofA Local 2000.10.14

 

 

这道题是比较经典的题目了。
就是给n根木棒,木棒两端都有颜色,判断能不能把木棒合并成一条,接触的木棒端必须是相同颜色的。

给定一些木棒,木棒两端都涂上颜色,求是否能将木棒首尾相接,连成一条直线,要求不同木棒相接的一边必须是相同颜色的。

 

貌似就是判断欧拉回路。

由图论知识可以知道,无向图存在欧拉路的充要条件为:

①     图是连通的;

②     所有节点的度为偶数,或者有且只有两个度为奇数的节点。

图的连通可以利用并查集去判断。

度数的统计比较容易。

数据比较大,首先需要将颜色的字符串和数字一一对应起来。

虽然可以用map,但是map效率不高,肯定会超时的。

 

最好的办法的是建立字典树。

将字符串和数字一一对应起来。

 

注意本题的数据有没有木棒的情况,要输出Possible。

 

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
using namespace std;

const int MAX=250000+10;
int par[MAX];
int dev[MAX];
int hash[MAX];
//定义字典树结构体
struct Trie
{
	Trie* next[26];
	int flag;
	Trie()
	{
		flag=-1;
	}
};

//*****************************************************************
Trie *root;
int ind;
//初始化root
void init()
{
	root=new Trie;
	memset(root,0,sizeof(Trie));
}
//*****************************************************************


//*****************************************************************
//将str插入以root为根节点的字典树中
int insert(char *str)
{
    int len = strlen(str);
    Trie *s = root;
    for (int i = 0; i < len; i++)
	{
		if (s->next[str[i] - 'a'])
            s = s->next[str[i] - 'a'];
        else
		{
            Trie* t = new Trie;
            memset(t, 0, sizeof (Trie));
            s->next[str[i] - 'a'] = t;
            s = t;
        }
	}
	return s->flag = ind++;
}
//*****************************************************************

//*****************************************************************
//查找字典树中是否有元素str
int find(char *str)
{
    int len = strlen(str);
    Trie *s = root;
    for (int i = 0; i < len; i++)
	{
		if (s->next[str[i] - 'a'])
            s = s->next[str[i] - 'a'];
        else
            return -1;
	}
	return s->flag;/////////////////////flag可能不标志为单词结尾
}
//*****************************************************************

int Get_par(int a)
//查找a的父亲节点并压缩路径
{
	if(par[a]==a)
		return par[a];
	//注意语句的顺序
	int pa=par[a];
	par[a]=Get_par(par[a]);
	return par[a];
}

void Merge(int a,int b)
//合并a,b
{
	int pa,pb;
	pa=Get_par(a);
	pb=Get_par(b);
	if(pa==pb)
		return;
	par[pa]=pb;
}


int main()
{
//	string a,b;
	char s1[15],s2[15];
	int i;
	int tag=0;
	init();
//	map<char [20],int>Map;
	for(i=0;i<MAX;i++)
	{
		par[i]=i;
		dev[i]=0;
		hash[i]=0;
	}
	ind=0;

//	freopen("in.txt","r",stdin);
	while(~scanf("%s%s",s1,s2))
	{
		int a=find(s1);
		int b=find(s2);

	//	printf("s1=%s   s2=%s\n",s1,s2);
	//	cout<<"a="<<a<<"  b="<<b<<endl;

		if(-1==a)
			a=insert(s1);
		if(-1==b)
			b=insert(s2);

	//	cout<<"a="<<a<<"  b="<<b<<endl;

		dev[a]++;
		dev[b]++;
		Merge(a,b);
	}



	int odddev=0;
	for(i=0;i<ind;i++)
	{
	//	printf("par[%d]=%d\n",i,par[i]);
		if(par[i]==i)tag++;
		if(dev[i]%2)odddev++;
		if(tag>1||odddev>2)
			break;
	}

	if((tag==1||tag==0)&&(odddev==2||odddev==0))
		printf("Possible\n");
	else 
		printf("Impossible\n");
/*	if(tag>1||odddev>2)
		printf("Impossible\n");
	else 
		printf("Possible\n");
		*/
	return 0;
}


 

你可能感兴趣的:(数据结构,图论)