[2016-03-17][HDU][1829][A Bug's Life]

  • 时间:2016-03-17 17:57:08 星期四

  • 题目编号:[2016-03-17][HDU][1829][A Bug’s Life]

  • 题目大意:

  • 分析:扩点并查集

  • 方法:

  • 并查集分析:
    • A 和 B 或者 A+n 和 B+n 在一组,表示A 和 B是同类
    • A 和 B+n 在一组,表示如果A是雄性,则B是雌性
    • B 和 A+n 在一组,表示如果B是雄性,则A是雌性
  • 每组数据一个空行
  • 方法2
  1. #include <cstring>
  2. #include <cstdio>
  3. using namespace std;
  4. typedef long long LL;
  5. #define CLR(x,y) memset((x),(y),sizeof((x)))
  6. #define FOR(x,y,z) for(int (x)=(y);(x)<(z);++(x))
  7. const int maxn = 2000 + 100;
  8. int fa[maxn * 2];
  9. void ini(int n){
  10. FOR(i,0,n + 1){
  11. fa[i] = i;
  12. }
  13. }
  14. int fnd(int x){
  15. return x == fa[x]?x:fa[x] = fnd(fa[x]);
  16. }
  17. int uni(int x,int y){
  18. x = fnd(x);
  19. y = fnd(y);
  20. if(x == y) return 0;
  21. fa[x] = y;
  22. return 1;
  23. }
  24. int insame(int x,int y){
  25. return fnd(x) == fnd(y);
  26. }
  27. int main(){
  28. //freopen("in.txt","r",stdin);
  29. //freopen("out.txt","w",stdout);
  30. int T,cntcase = 0;
  31. scanf("%d",&T);
  32. while(T--){
  33. int n,m,u,v,flg = 0;
  34. scanf("%d%d",&n,&m);
  35. ini((n + 1) * 2);
  36. FOR(i,0,m){
  37. if(!flg){
  38. scanf("%d%d",&u,&v);
  39. if(insame(u,v)){
  40. flg = 1;
  41. }else {
  42. uni(u,v + n);
  43. uni(u + n,v);
  44. }
  45. }else scanf("%*d%*d");
  46. }
  47. printf("Scenario #%d:\n",++cntcase);
  48. if(flg){
  49. puts("Suspicious bugs found!\n");
  50. }else puts("No suspicious bugs found!\n");
  51. }
  52. return 0;
  53. }
  • 方法2

  • 带权并查集

  • 分析

    • f(a,b) == 0,表示ab同类
    • f(a,b)表示ab的关系,则已知fa(a,b) fa(b,c),可以得到f(a,c) = (f(a,b),f(b,c))%2;
    • uni(int x,int y)中关系更新,已知f(x,y) = 0,f(x,fax),f(y,fay)那么f(fax,fay) = ((f(fax,x) + f(x ,y)%2) + f(y,fay))%2
  • 方法:维护和父节点的关系,在find的时候压缩路径,最后得到的就是和祖宗节点的关系

  • 注:刚开始第一个写成 ((a+b)&1 + c) ,这是错误的,因为+的优先级比&高,会先计算 1 + c再且
  1. #include <cstring>
  2. #include <cstdio>
  3. using namespace std;
  4. typedef long long LL;
  5. #define CLR(x,y) memset((x),(y),sizeof((x)))
  6. #define FOR(x,y,z) for(int (x)=(y);(x)<(z);++(x))
  7. const int maxn = 2000 + 100;
  8. int fa[maxn],relation[maxn];//relation[i] 表示i和父亲节点的关系,0表示同性,1表示异性
  9. void ini(int n){
  10. CLR(relation,0);
  11. FOR(i,0,n + 1){
  12. fa[i] = i;
  13. }
  14. }
  15. int fnd(int x){
  16. if(x == fa[x]) return x;
  17. int tmp = fa[x];
  18. fa[x] = fnd(fa[x]);
  19. relation[x] = (relation[tmp] + relation[x])&1 ;
  20. return fa[x];
  21. }
  22. int uni(int x,int y){
  23. int fax = fnd(x);
  24. int fay = fnd(y);
  25. if(fax == fay) return 0;
  26. fa[fax] = fay;
  27. //relation[fax] = (((relation[x]+1)&1) + relation[y])&1;//同余定理?
  28. relation[fax] = (relation[x] + 1 + relation[y])&1;
  29. return 1;
  30. }
  31. int isSame(int x,int y){
  32. int fax = fnd(x);
  33. int fay = fnd(y);
  34. return fax == fay && relation[x] == relation[y];
  35. }
  36. int main(){
  37. //freopen("in.txt","r",stdin);
  38. //freopen("out.txt","w",stdout);
  39. int T,cntcase = 0;
  40. scanf("%d",&T);
  41. while(T--){
  42. int n,m,u,v,flg = 0;
  43. scanf("%d%d",&n,&m);
  44. ini(n);
  45. FOR(i,0,m){
  46. if(!flg){
  47. scanf("%d%d",&u,&v);
  48. if(isSame(u,v)){
  49. flg = 1;continue;
  50. }else uni(u,v);
  51. }else scanf("%*d%*d");
  52. }
  53. printf("Scenario #%d:\n",++cntcase);
  54. if(flg) puts("Suspicious bugs found!\n");
  55. else puts("No suspicious bugs found!\n");
  56. }
  57. return 0;
  58. }


来自为知笔记(Wiz)


posted on 2016-03-17 18:17  红洋  阅读(107)  评论(0)    收藏  举报

导航