hdu 1116 并查集和欧拉路径

---恢复内容开始---

把它看成是一个图

只是需要欧拉路径就可以了 首尾能连成一条线即可

如果要判断这个图是否连通 得用并查集

在hrbust oj里面看答案学到的方法 不用各种for循环套着判断能否循环

只需要在union的时候做做调整 让比较大的父亲节点的父亲节点等于小的父亲节点 向1靠拢就可以 

但是在这里面 是向出现过的最小的字母的排序靠拢 所以要记录

而且for循环26个字母的时候 只对出现过的字母做判断它是否与最小的字母可以连通

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
using namespace std;
int ru[30];
int chu[30];
int fa[30];
int vis[30];
void init()
{
    for(int i=1;i<=26;i++)
    {
        ru[i]=0;
        chu[i]=0;
        fa[i]=i;
        vis[i]=0;
    }
}
int find(int i)
{
    return fa[i]==i?i:find(fa[i]);
}
void un(int a,int b)
{
    int aa=find(a);
    int bb=find(b);
    if(aa>bb)
        fa[aa]=bb;
    else fa[bb]=aa;
}
int main(){
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n;
        scanf("%d",&n);
        char s[2000];
        init();
        int minn=26;
        for(int i=0;i<n;i++)
        {
            scanf("%s",s);
            int a=s[0]-'a'+1;
            int len=strlen(s);
            int b=s[len-1]-'a'+1;
            chu[a]++;
            ru[b]++;
            un(a,b);
            vis[a]++;
            vis[b]++;
            if(a<minn)
                minn=a;
            if(b<minn)
                minn=b;
        }
        int yi=0;
        int er=0;
        int san=0;
        bool ok=true;
        for(int i=1;i<=26;i++)
        {
            if(ru[i]==chu[i])
                yi++;
            else if(ru[i]==chu[i]+1)
                er++;
            else if(ru[i]==chu[i]-1)
                san++;
            if(vis[i]!=0)
            {
                if(find(i)!=minn)
                    ok=false;
            }
        }
        if(yi==24&&er==1&&san==1&&ok==true)
            printf("Ordering is possible.\n");
        else if(yi==26&&ok==true)
            printf("Ordering is possible.\n");
        else printf("The door cannot be opened.\n");
    }
}

  

---恢复内容结束---

你可能感兴趣的:(hdu 1116 并查集和欧拉路径)