HDU ACM 1116 Play on Words(并查集 + 欧拉图)

http://acm.hdu.edu.cn/showproblem.php?pid=1116

题意:给出N个字符串,若所以字符串能连成一串则输出Ordering is possible.否则输出The door cannot be opened.

非常蛋疼的用了并查集.

思路是用并查集找出所有字符串能不能形成一个集合(只有一个几个 + 用欧拉图的特性判断能不能把所有的点连成一线

判断欧拉图:  欧拉回路:所有点的入度等于出度.

      欧拉通路:有且仅有两个点的入度不等于出度且入度与出度相差1.(注意:判断时相差2的不能忽略,也要进行记录)

View Code
  1 #include <iostream>
  2 #include <string>
  3 using namespace std;
  4 
  5 const int MAX = 30 + 10;
  6 int father[MAX];
  7 int rank1[MAX];
  8 int sign[MAX];
  9 
 10 void Make_Set(int x)//初始化
 11 {
 12     father[x] = x;
 13     rank1[x] = 0;
 14 }
 15 
 16 int Find_Set(int x)//找根节点
 17 {
 18     int i=0;
 19     while(father[x] != x)
 20     {
 21         sign[i++] = x;
 22         x = father[x];
 23     }
 24     for(i;i>=1;i--)
 25     {
 26         father[sign[i-1]] = x;
 27     }
 28     return x;
 29 }
 30 
 31 
 32 void Union(int x,int y)//合并
 33 {
 34     x = Find_Set(x);
 35     y = Find_Set(y);
 36     if(x == y)
 37     {
 38         return;
 39     }
 40     if(rank1[x] > rank1[y])
 41     {
 42         father[y] = x;
 43     }
 44     else if(rank1[x] < rank1[y])
 45     {
 46         father[x] = y;
 47     }
 48     else if(rank1[x] ==rank1[y]) 
 49     {
 50         father[x] = y;           
 51         rank1[y]++;             
 52     }
 53 }
 54 
 55 int main()
 56 {
 57     int used[MAX];
 58     int in[MAX] ;
 59     int out[MAX];
 60     int T;
 61     cin>>T;
 62     while(T--)
 63     {
 64         memset(used, 0, sizeof(used));
 65         memset(in, 0 ,sizeof(used));
 66         memset(out, 0 ,sizeof(used));
 67 
 68         int n;
 69         cin>>n;
 70         int i;
 71         for(i=0;i<MAX-1;i++)
 72         {
 73             Make_Set(i);
 74         }
 75         for(i=0;i<n;i++)
 76         {
 77             char str[1100];
 78             cin>>str;
 79             used[str[0] - 'a'] = 1;
 80             used[str[strlen(str)-1] - 'a'] = 1;
 81             Union(str[0] - 'a',str[strlen(str)-1] - 'a');
 82             out[str[0] - 'a']++;
 83             in[str[strlen(str)-1] - 'a']++;
 84         }
 85         int sum = 0;
 86         int mark = 0;
 87         int mark1 = 0;
 88         int mark2 = 0;
 89         int mark3 = 0;
 90         int num = 0;
 91         for(i=0;i<MAX-1;i++)
 92         {
 93             if(used[i])
 94             {
 95                 num++;
 96             }
 97             if(used[i] && father[i] == i)
 98             {
 99                 sum++;
100             }
101 
102 
103             if (used[i] && in[i] != out[i] )
104             {
105                 if(used[i] && in[i] - out[i] == 1)
106                 {
107                     mark1++;
108                 }
109                 else if(used[i] && out[i] - in[i] == 1)
110                 {
111                     mark2++;
112                 }
113                 else
114                 {
115                     mark=1;
116                 }
117 
118             }
119             else if (used[i] && in[i] == out[i])
120             {
121                 mark3++;
122             }
123         }
124 
125 
126         if (mark)
127         {
128             cout<<"The door cannot be opened."<<endl;
129         }
130         else
131         if(sum == 1 && ((mark1 == 1 && mark2 == 1) || mark3 == num)  )
132         {
133             cout<<"Ordering is possible."<<endl;
134         }
135         else
136         {
137             cout<<"The door cannot be opened."<<endl;
138         }
139 
140 
141     }
142 
143     return 0;
144 }

 

posted @ 2012-08-26 13:50  zx雄  阅读(261)  评论(0编辑  收藏  举报