zoukankan      html  css  js  c++  java
  • HDU1116Play on Words(欧拉回路+并查集)

    题意:

           给你一连串的单词,每个单词只要能够首位相连就可以输出  Ordering is possible.否则输出The door cannot be opened.
    解题思路:

           典型的欧拉回路,把每个单词的首字母跟尾字母作为节点,然后算每个节点的入度跟出度,

           1.首先应判断这个图是否有连通分量,如果有连通分量,那么这个图就不满足。

           2.当图没有连通分量满足时,算如果每个节点的入度于出度都是偶数,那么就是一个欧拉回路,这种情况满足。

              另一种是欧拉通路,即一个节点只有入度,另一个节点只有出度就可以满足。

    发发牢骚:

           因为初始化的时候i=1;i<=MAX;i++时这个=号越界了,搞得我头都大了。。

           玄得狠,不过也证明一个问题,熟悉的错不了,认真分析一遍还是可以分析出来的,细心透彻地分析很重要。

    代码:

    #include<iostream> 
    #include<string> 
    using namespace std; 
     
    const int MAX=30
    int father[MAX],dep[MAX],in[MAX],out[MAX],visited[MAX]; 
     
    int find_set(int x) 

        if(x!=father[x]) 
        { 
            father[x]=find_set(father[x]);//回溯压缩路径 
        } 
        /*所有的子节点的根都归到boss下*/ 
        return father[x]; 

     
    void union_set(int f1,int f2) 

        f1=find_set(f1); 
        f2=find_set(f2); 
        if(f1==f2) 
            return ; 
        if(dep[f1]>dep[f2]) 
        { 
            father[f2]=f1; 
        } 
        else 
        { 
            if(dep[f1]==dep[f2]) 
            { 
                dep[f2]++; 
            } 
            father[f1]=f2; 
        } 
        return ; 

     
    void init() 

        for(int i=0;i<MAX;i++) 
        { 
         
            father[i]=i;//父节点         
            dep[i]=0;//并查集的秩 
            in[i]=0
            out[i]=0
            visited[i]=0;//节点是否访问过 
        } 

     
    int main(void

        int cas,num,i,a,b,flag,count,k,p[MAX]; 
        string str; 
        scanf("%d",&cas); 
        while(cas--) 
        { 
            scanf("%d",&num);//单词个数 
            init(); 
            for(i=1;i<=num;i++) 
            { 
                cin>>str; 
                a=str[0]-'a'
                b=str[str.size()-1]-'a'
                in[a]++;//入度 
                out[b]++;//出度 
                visited[a]=1
                visited[b]=1
                union_set(a,b); 
            } 
            /*判断有向图是否连通*/ 
            for(i=0,count=0;i<MAX;i++) 
            { 
                if((visited[i])&&father[i]==i) 
                    count++; 
            } 
            flag=0;//通 
     
            if(count!=1
            { 
                cout<<"The door cannot be opened."<<endl; 
                continue
            } 
            for(i=0,k=0;i<MAX;i++) 
            { 
                if(in[i]!=out[i])//找出入度与出度不相同的点 
                    p[k++]=i; 
            } 
            if(k==0||k==2)//白开水思路 
            { 
                if(k==0
                {         
                    flag=0
                } 
                else 
                { 
                    if( out[p[0]]-in[p[0]]==1 && in[p[1]]-out[p[1]]==1   ||( out[p[1]]-in[p[1]]==1 && in[p[0]]-out[p[0]]==1 ) ) 
                    { 
                        flag=0
                    } 
                    else 
                        flag=1
                } 
            } 
            else 
            { 
                flag=1
            } 
            if(flag) 
                cout<<"The door cannot be opened."<<endl; 
            else 
                cout<<"Ordering is possible."
    <<endl; 
        } 
        //system("pause"); 
        return 0

  • 相关阅读:
    51nod1229 序列求和 V2
    51nod 1228、1258 序列求和
    题解P3711:【仓鼠的数学题】
    伯努利数学习笔记的说...
    题解 P4692 【[Ynoi2016]谁的梦】
    积性函数与卷积
    题解 P5065 【[Ynoi2014]不归之人与望眼欲穿的人们】
    [Ynoi2018]末日时在做什么?有没有空?可以来拯救吗?
    [51nod1965]奇怪的式子
    PGCD2
  • 原文地址:https://www.cnblogs.com/cchun/p/2520117.html
Copyright © 2011-2022 走看看