POJ2513 欧拉 + 字典树

POJ 2513


有N根木棒,一根木棒有2头,我们把每头涂色(相同或不同),如果2根木棒有相同颜色的一端就可以连接,颜色全部不同就不能连接,现在给你N根木棒以及它们的颜色,问最后能不能链接成1条链。

欧拉回路的问题,判断联通  以及  奇点个个数

输入为字符串,开始并不知道怎么弄,参考了下别人的报告,用字典树处理(学到的新东西),

 

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;

const int N = 15;
const int M = 1000010;

struct node
{
	int num;
	node* next[26];
}*Head;

char u[N], v[N];
int num, n, top, total;
bool flag;
int pre[M], in[M];
node pnode[M];

int fin(int x) //递归+路径压缩
{
	return pre[x] == -1 ? x : (pre[x] = fin(pre[x]));
}

void Uni(int x, int y) //合并
{
	int root1 = fin(x);
	int root2 = fin(y);
	if(root1 != root2)
		pre[root2] = root1;
}

int insert(char str[]) //返回数组下标
{
	Head = &pnode[0];
	int len = strlen(str);
	for(int i = 0; i < len; ++i)
	{
		int temp = str[i] - 'a';
		if(Head->next[temp] == NULL)
			Head->next[temp] = &pnode[++num];
		Head = Head->next[temp];
	}
	if(Head->num == 0)
		Head->num = top++;
	return Head->num;
}

void init()
{
	num = total = 0; top = 1; flag = true;
	memset(in,0,sizeof(in));memset(pre,-1,sizeof(pre));
	for(int i = 0; i <M ; ++i)
	{
		pnode[i].num = 0;
		for(int j = 0; j < 26; ++j)
			pnode[i].next[j] = NULL;
	}
}

int main()
{
	int tmp, temp;
	init();
	while(scanf("%s %s", u, v) != EOF)
	{
		tmp = insert(u); temp = insert(v);
		in[tmp]++; in[temp]++;
		Uni(tmp, temp);
	}
	int root = fin(1);
	for(int i = 1; i < top; ++i) //判断是否联通,奇点
	{
		if(root != fin(i))
		{
			flag = false;
			break;
		}
		if(in[i] & 1)
			total++;
		if(total > 2)
			break;
	}
	// 奇点为0  环 ,奇点为2  链
	puts(((total == 0 || total == 2) && flag == true) ? "Possible" : "Impossible");
	return 0;
}

  

posted @ 2015-06-22 23:40  Przz  阅读(159)  评论(0编辑  收藏  举报