hdu 1116 欧拉通路+并查集

题意:给你一些英文单词,判断所有单词能不能连成一串,前一个单词的最后一个字母和后一个单词的首字母相同则可以相连。
 

判断是否构成欧拉回路或者欧拉通路(以下是别人博客里的一段)

1.并查集判断连通

2.将每个单词取出首字母和尾字母,转换为一条边,然后加入对应的连通分量中。如果这个字母出现过,visit数组标记为true。同时起点出度加1,终点入度加1.

3.判断一下:

1)这个图必须是连通的,即根结点只有一个。如果不是,直接结束本次算法

2)如果这个图是连通的,判断每个结点的入度和出度情况。

        如果这个图是欧拉路,则每个顶点的出度等于入度。即out[i] = in[i]

如果这个图是半欧拉图,则起点的出度比入度大1,终点的入度比出度大1.其余顶点的出度等于入度。

如果满足上述条件,就可以将所有单词链接起来,否则不能。

当然,在判断出度入度的时候还有一点需要注意,那就是除了起点终点以外的顶点,出度必须等于入度(出度入度可以同时为2,即环),但是起点和终点必须保证出度和入度之差为1。

  1 #include<iostream>
  2 #include<algorithm>
  3 #include<cmath>
  4 #include<vector>
  5 #include<string.h>
  6 #include<string>
  7 
  8 using namespace std;
  9 
 10 const int MAX_N = 30;
 11 int pre[MAX_N],father[MAX_N];
 12 int iin[MAX_N],oout[MAX_N];
 13 bool visited[MAX_N];
 14 int n;
 15 
 16 void init()
 17 {
 18     for(int i = 0; i < MAX_N; i++)
 19     {
 20         pre[i] = i;
 21         iin[i]=0;
 22         oout[i]=0;
 23         father[i] = 0;
 24         visited[i]=0;
 25     }
 26 }
 27 
 28 int find_root(int x)
 29 {
 30     int r = x;
 31     while(pre[r]!=r)
 32         r = pre[r];
 33     
 34     int i = x,j;
 35     while(i!=r)
 36     {
 37         j = pre[i];
 38         pre[i] = r;
 39         i = j;
 40     }
 41     return r;
 42 }
 43 
 44 void mix(int x,int y)
 45 {
 46     int xx = find_root(x);
 47     int yy = find_root(y);
 48     if(xx!=yy)
 49         pre[yy] = xx;
 50 }
 51 int main()
 52 {
 53     cin.sync_with_stdio(false);
 54     int t,st,en;
 55     cin>>t;
 56     while(t--)
 57     {
 58         init();
 59         cin>>n;
 60         string s;
 61         for(int i = 1; i <= n; i++)
 62         {
 63             cin>>s;
 64             st = s[0]-'a';
 65             en = s[s.length()-1]-'a';
 66             mix(st,en);
 67             oout[st]++;
 68             iin[en]++;
 69             visited[st]=1;
 70             visited[en]=1;
 71         }
 72        
 73         for(int i = 0; i < 26; i++)
 74         {
 75             if(visited[i])
 76                 father[i] = find_root(i);
 77         }
 78         int ii = 0,oo = 0, flag = 0,roots = 0,te = 0;
 79         for(int i = 0; i < 26; i++)
 80         {
 81             if(visited[i])
 82             {
 83                 if(iin[i]!=oout[i])
 84                 {
 85                     if(iin[i]-oout[i]==1)
 86                         ii++;
 87                     else
 88                         if(oout[i]-iin[i]==1)
 89                             oo++;
 90                     else
 91                     {
 92                         te++;
 93                     }
 94                 }
 95                 if(father[i]==i)
 96                     roots++;
 97                 
 98             }
 99         }
100         if(roots==1 &&((ii==0 && oo==0 && te==0)|| (ii==1 && oo==1 && te==0)))
101             flag = 1;
102         if(flag==1)
103             cout<<"Ordering is possible."<<endl;
104         else
105             cout<<"The door cannot be opened."<<endl;
106             
107         
108     }
109     return 0;
110 }
原文地址:https://www.cnblogs.com/Xycdada/p/7374208.html