HDU1116欧拉回(通)路+并查集

HDU1116欧拉回(通)路+并查集
http://acm.hdu.edu.cn/showproblem.php?pid=1116

无向图存在欧拉回路的条件:
一个无向图存在欧拉回路,当且仅当该图所有顶点度数都是偶数或该图除了两个奇数度顶点外其余顶点度数都是偶数。

有向图存在欧拉回路的条件:
1)所有的点联通
2)欧拉回路中所有点的入度和出度一样。
3)欧拉通路中终点的入度 - 出度 = 1,起点的 初度 - 入度 = 1, 其他的所有点入度 = 出度;

入度:以某顶点为弧头,终止与该顶点的弧的数目称为该顶点的入度。 
出度:以某顶点为弧头,起始与该顶点的弧的数目称为该顶点的出度。

这道题只需记录入度和出度信息,所以判断是否连通时可以当做是无向图来做,用并查集判断复杂度低。
// 并查集判断是否连通,也可以用其他方法判断无向图是否连通,并查集复杂度低
// 因为我们只考虑出度、入度信息,所以可以当做无向图处理
// 出度、入度判断是否存在欧拉通路或欧拉回路
#include  < iostream >
#include 
< string >

using   namespace  std;

const   int  M = 26 ;
int  parent[M];
int  pin[M],pout[M]; // 记录出度、入度信息
int  s[M];           // 记录出度与入度不相等的点
bool  visit[M];

void  UFunion( int  i, int  j)
{
    
int temp=parent[i]+parent[j];
    
if(parent[i]<=parent[j])
    
{
        parent[i]
=temp;
        parent[j]
=i;
    }

    
else
    
{
        parent[j]
=temp;
        parent[i]
=j;
    }

}


int  UFfind( int  i)
{
    
int j,temp;
    
for(j=i;parent[i]>=0;i=parent[i]); //注意parent[i]>=0,不是parent[i]>0,因为parent[i]可能等于0
    while(j!=i)
    
{
        temp
=parent[j];
        parent[j]
=i;
        j
=temp;
    }

    
return i;
}


int  main()
{
    
int i,j,pi,pj,t,c,k;
    
string str;
    cin
>>t;
    
while(t--)
    
{
        cin
>>k;
        c
=0;
        memset(parent,
-1,sizeof(parent));
        memset(pin,
0,sizeof(pin));
        memset(pout,
0,sizeof(pout));
        memset(visit,
0,sizeof(visit));
        
while(k--)
        
{
            cin
>>str;
            i
=str[0]-'a';
            j
=str[str.length()-1]-'a';
            visit[i]
=visit[j]=true;
            pout[i]
++;
            pin[j]
++;
            pi
=UFfind(i);
            pj
=UFfind(j);
            
if(pi!=pj)
            
{
                UFunion(pi,pj);
            }

        }

        
        
for(c=0,i=0;i<M;i++//求出有多少连通分量
            if(visit[i] && parent[i]<0)
                c
++;
        
if(c>1//如果有向图不是连通图
        {
            cout
<<"The door cannot be opened.\n";
            
continue;
        }

        
        
for(c=0,i=0;i<M;i++)//记录出入不等于入度的点
        {
            
if(visit[i] && pin[i]!=pout[i])
                s[c
++]=i;
        }

        
if(c==0)  //欧拉回路存在
        {
            cout
<<"Ordering is possible.\n";
            
continue;
        }

        
if(c==2 && ((pin[s[0]]-pout[s[0]]==1 && pout[s[1]]-pin[s[1]]==1|| (pin[s[1]]-pout[s[1]]==1 && pout[s[0]]-pin[s[0]]==1)))
        
{                                    //注意上面的格式是:if( (条件1) && (条件2)),条件2=条件3 || 条件4
            cout<<"Ordering is possible.\n"//欧拉通路存在,一个终点,一个始点
        }

        
else
        
{
            cout
<<"The door cannot be opened.\n";
        }

    }

    
return 0;
}



你可能感兴趣的:(HDU1116欧拉回(通)路+并查集)