poj2513

题意:给定一张图,每个点是一种颜色,用一个单词表示,问是否存在欧拉通路。

分析:欧拉路径问题,求是否有欧拉通路

1.定理:无向图G有欧拉通路的充分必要条件是G为连通图,并且G仅有两个奇度结点或者无奇度结点。
(1)当G是仅有两个奇度结点的连通图时,G的欧拉通路必以此两个结点为端点。
(2)当G是无奇度结点的连通图时,G必有欧拉回路。

2.一个有向图D具有欧拉通路,当且仅当D是连通的,且除了两个顶点外,其余顶点的入度均等于出度,这两个特殊的顶点中,一个顶点的入度比出度大1,另一个顶点的入度比出度小1. 推论:一个有向图D是欧拉图(具有欧拉回路),当且仅当D是连通的,且所有顶点的出度等于入度。

3.trie树是一种存储名称的普遍方法。

解法:并查集判断是否连通,用trie存储每种颜色。看度是否符合要求。

View Code
#include < iostream >
#include
< cstdio >
#include
< cstdlib >
#include
< cstring >
using namespace std;

#define L 100
#define maxn 500050

struct Node
{
Node
* next[ 26 ];
int x, id;
bool end;
}trie[
550000 ], * color[maxn];

int ncount = 0 , colornum = 0 , father[maxn];

int getanc( int a)
{
if (father[a] == a)
return a;
return father[a] = getanc(father[a]);
}

void merge( int a, int b)
{
father[getanc(a)]
= getanc(b);
}

Node
* ins(Node * proot, char * word)
{
if (word[ 0 ] == ' \0 ' )
{
if ( ! proot -> end)
{
proot
-> end = true ;
proot
-> id = colornum;
color[colornum
++ ] = proot;
father[proot
-> id] = proot -> id;
}
proot
-> x ++ ;
return proot;
}
int index = word[ 0 ] - ' a ' ;
if ( ! proot -> next[index])
{
ncount
++ ;
proot
-> next[index] = trie + ncount;
}
return ins(proot -> next[index], word + 1 );
}

int main()
{
// freopen("t.txt", "r", stdin);
memset(trie, 0 , sizeof (trie));
char st[L];
while (gets(st) && strcmp(st, "" ) != 0 )
{
char * word1 = strtok(st, " " );
char * word2 = strtok(NULL, " " );
Node
* a = ins(trie, word1);
Node
* b = ins(trie, word2);
merge(a
-> id, b -> id);
}
int temp = 0 ;
for ( int i = 0 ; i < colornum; i ++ )
if (father[i] == i)
temp
++ ;
if (temp > 1 )
{
printf(
" Impossible\n " );
return 0 ;
}
temp
= 0 ;
for ( int i = 0 ; i < colornum; i ++ )
if (color[i] -> x & 1 )
temp
++ ;
if (temp == 2 || temp == 0 )
printf(
" Possible\n " );
else
printf(
" Impossible\n " );

return 0 ;
}

你可能感兴趣的:(poj)