nyoj-一笔画问题(欧拉图+并查集)

来源:互联网 发布:cs基地杀人案 知乎 编辑:程序博客网 时间:2024/04/30 08:08

nyoj原题

#include<stdio.h>#define Max 1001int father[Max];int rank[Max];void make_set(int x){    father[x]=x;    rank[x]=0;}int find_set(int x){    if(father[x]!=x)    father[x]=find_set(father[x]);    return father[x];}int main(){    int T;int P,Q,a,b,i;    scanf("%d",&T);    while(T--)    {        int count=0;        scanf("%d%d",&P,&Q);        for(i=1;i<=P;i++)        make_set(i);        while(Q--)        {            scanf("%d%d",&a,&b);            rank[a]++;rank[b]++;            a=find_set(a);b=find_set(b);            if(a!=b)            father[a]=father[b];        }        for(i=1;i<=P;i++)            {                if(find_set(i)==i) count++;                if(count>1){                    count=-1;break;                }            }            if(count==-1)            printf("No\n");            else{                count=0;                for(i=1;i<=P;i++)                if(rank[i]%2==1) count++;                if(count==0||count==2)                printf("Yes\n");                else                printf("No\n");            }    }    return 0;

附加:判断欧拉图的条件:
1.图是连通的
2.奇节点(领边数为奇数)为2或0

并查集算法模板:

int father[MAX];   /* father[x]表示x的父节点*/  int rank[MAX];     /* rank[x]表示x的秩*/  /* 初始化集合*/  void Make_Set(int x)  {      father[x] = x; //根据实际情况指定的父节点可变化      rank[x] = 0;   //根据实际情况初始化秩也有所变化  }  /* 查找x元素所在的集合,回溯时压缩路径*/  int Find_Set(int x)  {      if (x != father[x])      {          father[x] = Find_Set(father[x]); //这个回溯时的压缩路径是精华      }      return father[x];  }  /* 按秩合并x,y所在的集合 下面的那个if else结构不是绝对的,具体<strong>根据实际情况</strong>变化 但是,宗旨是不变的即,按秩合并,实时更新秩。 */  void Union(int x, int y)  {      x = Find_Set(x);      y = Find_Set(y);      if (x == y) return;      if (rank[x] > rank[y])      {          father[y] = x;          rank[x] += rank[y];      }else      {          if (rank[x] == rank[y])          {              rank[y]++;          }          father[x] = y;      }  }  
1 0
原创粉丝点击