原题链接:Colored Sticks
题意:给一些木棒,木棒两端图上颜色,将端点颜色相同的木棒连在一起,问是否能连成一条直线。
思路:能构成欧拉通路的话就是题解,判断欧拉欧拉通路:1.是连通图 2.有两个奇数度顶点,其余都是偶数度的。
判断连通性用并查集,顶点度数的话直接记录
要用并查集,首先单词的数量比较多,用数组储存占用空间较大,要用字典树(trie树)储存,并且将每个单词转换为一个编号
//poj
#include <cstdio>
#include <cstring>
using namespace std;
const int MAX_N = 500010;
int cnt = 0;
int par[MAX_N];
int degree[MAX_N];
struct Trie{
int id;
Trie *next[26];
Trie(){
id = 0;
memset(next, NULL, sizeof(next));
}
}*root;
void init(){
for(int i = 0;i < MAX_N;i ++){
par[i] = i;
}
}
int find(int x){
return x == par[x] ? x : par[x] = find(par[x]);
}
void unite(int x, int y){
par[find(x)] = find(y);
}
int find_id(char s[]){ //字典树查找单词对应的编号
int i, len = strlen(s);
Trie *p = root;
for(i = 0;i < len;i ++){
int index = s[i] - 'a';
if(p->next[index] == NULL)
p->next[index] = new Trie;
p = p->next[index];
}
if(p->id == 0) p->id = ++cnt; //id记录单词的遍号
return p->id;
}
int main(){
char s1[12], s2[12];
init();
root = new Trie;
while(~scanf("%s%s", s1, s2)){
int id1 = find_id(s1);
int id2 = find_id(s2);
unite(id1, id2);
++ degree[id1];
++ degree[id2];
}
int count = 0, f = find(1);
for(int i = 1;i <= cnt;i ++){
if(degree[i] & 1) ++ count;
if(count > 2 || find(i) != f){
printf("Impossible\n");
return 0;
}
}
printf("Possible\n");
return 0;
}
原题链接:
色彩棒
//nyoj
#include <cstdio>
#include <cstring>
using namespace std;
const int MAX_N = 500010;
int cnt;
int par[MAX_N];
int degree[MAX_N];
struct Trie{
int id;
Trie *next[26];
Trie(){
id = 0;
memset(next, NULL, sizeof(next));
}
}*root;
void init(){
cnt = 0;
for(int i = 0;i < MAX_N;i ++){
degree[i] = 0;
par[i] = i;
}
}
int find(int x){
return x == par[x] ? x : par[x] = find(par[x]);
}
void unite(int x, int y){
par[find(x)] = find(y);
}
int find_id(char s[]){ //字典树查找单词对应的编号
int i, len = strlen(s);
Trie *p = root;
for(i = 0;i < len;i ++){
int index = s[i] - 'a';
if(p->next[index] == NULL)
p->next[index] = new Trie;
p = p->next[index];
}
if(p->id == 0) p->id = ++cnt; //id记录单词的遍号
return p->id;
}
void del(Trie* root)
{
if(root == NULL) return;
for(int i=0;i<26;i++)
{
if(root->next[i]!=NULL)
{
del(root->next[i]);
}
}
delete root;
}
int main(){
int k, n;
char s1[15], s2[15];
scanf("%d", &k);
while(k --){
root = new Trie;
init();
scanf("%d", &n);
while(n --){
scanf("%s%s", s1, s2);
int id1 = find_id(s1);
int id2 = find_id(s2);
unite(id1, id2);
++ degree[id1];
++ degree[id2];
}
int count = 0, f = find(1), flag = 0;
for(int i = 1;i <= cnt;i ++){
if(degree[i] & 1) ++ count;
if(count > 2 || find(i) != f){
flag = 1;
break;
}
}
if(flag)
printf("Impossible\n");
else
printf("Possible\n");
del(root);
}
return 0;
}