• 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

  • 相关阅读:
    奶酪工厂
    P1080 国王游戏(非高精版)
    【洛谷P2150】[NOI2015] 寿司晚宴
    【洛谷P3349】[ZJOI2016]小星星
    【洛谷P5785】[SDOI2012]任务安排
    【模板】严格次短路
    【洛谷P3647】[APIO2014]连珠线
    2021.10.27NOIP模拟总结
    【树形DP】CF1016F Road Projects
    2021CSP-S 总结
  • 原文地址:https://www.cnblogs.com/cchun/p/2520117.html
Copyright © 2020-2023  润新知