POJ 2513 Colored Sticks 解题报告
解题思路:由欧拉通路的结论,首先我们要统计出入度,如果各个颜色各自的度数和中只有1个是奇数或者有3个及以上为奇数,那么就不可能,那么如何统计度数呢?建立字典树,如果到达一个颜色字符串的末尾,这个颜色的度数+1。通过以上条件后进行下一步判断,如何判断木条能连成一根呢?用并查集,除了顶端颜色的最上级就是其自身外,其他颜色的最上级都应该是顶端颜色,统计并查集中颜色等于自身的次数,如果超过1,就是不可能。通过以上全部条件就能连接成一根木条了。
#include<iostream>
#include<math.h>
#include<iomanip>
#include<algorithm>
#include<iostream>
#include<math.h>
#include<iomanip>
#include<algorithm>
#include<queue>
#include<cstring>
#include<string>
#include<map>
#include<stack>
#include<stdio.h>
#include<cstdio>
#include<stdlib.h>
#include<fstream>
#include<iomanip>
#pragma warning(disable:4996)
#define INF 0x3f3f3f3f
#define ll long long
#define PI acos(-1.0)
const int N = 500010;
const int maxn = 1e9;
using namespace std;
struct trie {
bool flag;//标记字符串是否到达末尾
int index;
trie* next[27];
trie() {
flag = false;
index = 0;
memset(next, 0, sizeof(next));
}
}root;
int color;
int degree[N];
int ancestor[N];
int find(int x)//寻找x最上级
{
if (ancestor[x] != x)
ancestor[x] = find(ancestor[x]);
return ancestor[x];
}
void union_set(int a, int b)//使a和b的上级相同
{
int pa = find(a);
int pb = find(b);
ancestor[pb] = pa;
return;
}
int ha(char* s)
{
trie* p = &root;
int len = 0;
while(s[len]!='\0')//建立字典树
{
int index = s[len++] - 'a';
if (!p->next[index])
p->next[index] = new trie;
p=p->next[index];
}
//循环结束后已到达字符串末尾
if (p->flag)
return p->index;
else
{
p->flag = true;
p->index = ++color;//每一种颜色都有自己的标号
return p->index;
}
}
int main()
{
memset(degree, 0, sizeof(degree));
color = 0;
for (int i = 1; i <= N; i++)
{
ancestor[i] = i;//一开始并查集中元素的最上级都是自己
}
char a[11], b[11];
while (~scanf("%s %s",&a,&b))
{
int i = ha(a);
int j = ha(b);
degree[i]++;//统计度数,出入度一起算
degree[j]++;
union_set(i, j);
memset(a, 0, sizeof(a));
memset(b, 0, sizeof(b));
}
int num = 0;
int cnt = 0;
for (int i = 1; i <= color; i++)
{
if (degree[i] % 2 == 1)
num++;
if (num > 2)
{
printf("Impossible\n");
return 0;
}
if (ancestor[i]==i)
{
cnt++;
}
if (cnt > 1)
{
printf("Impossible\n");
return 0;
}
}
if (num == 1)
printf("Impossible\n");
else
printf("Possible\n");
}