题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=230
分析:题目意思是给你一些棒子,两端颜色不同,问相同的颜色两两相连,问是否会连成一个环。连成一个环是欧拉回路,开始的时候有一个题目是判定树一样是判断欧拉回路,用并查集和奇点的个数判断,以棒子为边,以颜色为点,问题是颜色是字符串,转化为并查集中的点是个难点,可以用并查集求解,将边转换为点~~~具体见代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<algorithm>
using namespace std;
const int MAX=250001;
#define CLR(arr,val) memset(arr,val,sizeof(arr))
int indgree[MAX],total;
char s1[26],s2[26];
class UnionFindSet{
public:
UnionFindSet(){Init();}
int Find(int u)
{ return father[u]==-1?u:Find(father[u]);
}
int Rank(int u) {return rank[u];}
void Union(int u,int v)
{ u=Find(u);
v=Find(v);
if(u==v) return ;
if(rank[u]>rank[v])
{ rank[u]+=rank[v];
father[v]=u;
}
else
{ rank[v]+=rank[u];
father[u]=v;
}
}
void Init()
{ CLR(father,-1);
fill(rank,rank+MAX,1);
}
private:
int father[MAX];
int rank[MAX];
};
struct Trie
{ int num;
bool flag;
Trie *node[26];
Trie()
{ num=-1;
flag=false;
CLR(node,0);
}
}*root;
int Search(char *s)
{ Trie *R=root;
for(int i=0;i<strlen(s);++i)
{ if(!R->node[s[i]-'a'])
R->node[s[i]-'a']=new Trie;
R=R->node[s[i]-'a'];
}
if(R->flag) return R->num;
R->flag=true;
R->num=total++;
return R->num;
}
int main()
{ UnionFindSet U;
int k,n;
scanf("%d",&k);
while(k--)
{ U.Init();
CLR(indgree,0);
total=0;
scanf("%d",&n);
getchar();
root=new Trie;
for(int i=0;i<n;i++)
{ scanf("%s %s",s1,s2);
int u=Search(s1);
int v=Search(s2);
indgree[u]++;
indgree[v]++;
U.Union(u,v);
}
int sum=0;
for(int i=0;i<total;i++)
if(indgree[i]%2) sum++;
if((sum==0||sum==2)&&U.Rank(U.Find(1))==total||n==0) puts("Possible");
else puts("Impossible");
}
return 0;
}
开始时用class定义类,做了半天,还是没有做出来,就是那个私有函数比较麻烦~~但应该还是能做,想想~poj 2513:题目链接:http://poj.org/problem?id=2513得注意下,数组不能只开250001,这样会RE,得开510000,还有就是空数据为Possible~~~