NYOJ 99 POJ 2337

View Code
  1 /*

  2 1.先用并差集判断图是否连通 

  3 2.判断是否存在欧拉路或欧拉回路

  4 3.DFS求欧拉路径 

  5 */ 

  6 #include<iostream>

  7 #include<cstdio>

  8 #include<cstring>

  9 #include<algorithm>

 10 using namespace std;

 11 

 12 const int size = 1005;

 13 

 14 struct nodedge

 15 {

 16    int e;//单词的最后一个字母  对应的数字 相当于:路径的末端 

 17    int id;//记录这个单词是第几个单词 

 18    int next;//首字母相同的单词连起来 

 19    bool vis;//标志这个单词是否用过 

 20 }edge[size];

 21 

 22 struct nodechar

 23 {

 24   char ch[32];//存放单词 

 25 }cha[size];

 26 

 27 int degree[27];//计算出现的 字母的 初度入度 

 28 int father[27];//并差集 

 29 int rank[27];

 30 bool show[27];

 31 int stack[size]; //存放欧拉路径 

 32 int k[27];// k[i] 存放以 以  i 为首的字母链的所在位置  

 33 int st;//记录路径 stack[] 

 34 int point;//记录出现了几个字母 

 35 int M;

 36 

 37 int find(int x)//非递归压缩路径 

 38 {

 39    int i=x;

 40    while(i!=father[i])

 41      i=father[i];

 42    int j=x;

 43    while(j!=i)

 44     {

 45       int k= father[j];

 46       father[j]=i;

 47       j=k;

 48     }

 49    return i;

 50 }

 51 

 52 void uion(int x,int y)//并差集 合并两个子集 

 53 {

 54    x=find(x);

 55    y=find(y);

 56    if(x!=y)

 57     {

 58       if(rank[x]>=rank[y])

 59        {

 60          rank[x]+=rank[y];

 61          father[y]=x;

 62        }

 63       else 

 64       {

 65         rank[y]+=rank[x];

 66         father[x]=y;

 67       }

 68     }

 69 }

 70 

 71 bool cmp(nodechar x,nodechar y)

 72 {

 73    return strcmp(x.ch,y.ch)>0; 

 74 } 

 75 

 76 void init()

 77 {

 78    int i,len;

 79    for(i=0;i<26;++i)

 80     {

 81       degree[i]=0;

 82       father[i]=i;

 83       rank[i]=1;

 84       show[i]=false;

 85       k[i]=-1;

 86     }

 87    st=0;

 88    point=0;

 89    

 90    for(i=0;i<M;++i)

 91     scanf("%s",cha[i].ch);

 92     

 93    sort(cha,cha+M,cmp);//从 大  到  小 排序 (插入到之后得到的是从小大排序) 

 94    for(i=0;i<M;++i)

 95     printf("%s\n",cha[i].ch); 

 96    

 97    for(i=0;i<M;++i)

 98     {

 99        len=strlen(cha[i].ch);

100        int h1 = cha[i].ch[0]-'a';

101        int h2 = cha[i].ch[len-1]-'a';

102        

103        edge[i].e=h2;//依次插入之后 变成从  小到大排序 

104        edge[i].id=i;

105        edge[i].vis=false;

106        edge[i].next=k[h1];

107        k[h1]=i;

108        degree[h1]--;//注意这里设计的 

109        degree[h2]++;

110        if(!show[h1]){show[h1]=true;point++;}

111        if(!show[h2]){show[h2]=true;point++;}

112        uion(h1,h2);

113     }

114     for(i=0;i<26;++i)

115      if(show[i])find(i);

116 }

117 

118 int start()

119 {

120     int odd=0,t1,t2;//t1,t2记录两个奇数度结点的位置 

121     int i;

122 

123     for(i=0;i<26;++i)  

124      if(show[i])

125       {

126         if(rank[father[i]]!=point)return -1;

127         if(!degree[i])continue;

128         if(degree[i]>1 || degree[i]<-1)return -1;//少了这个条件就错了 (也即可能有  odd==2,奇数的出度,或入度不是 1,或-1) 

129         if(0==odd)t1=i;

130         if(1==odd)t2=i;

131         odd++;

132       }

133 

134      if(odd==1 || odd>2 || (degree[t1]+degree[t2]))return -1;//第三个条件限制一个入度为 1 ,一个出度为1 

135      if(odd==2)//存在欧拉路 

136       {

137         if(degree[t1]==-1)return t1;

138         else return t2;

139       }

140      if(odd==0)//存在欧拉回路

141       {

142         for(i=0;i<26;++i)

143          if(show[i])return i;

144       } 

145      return -1;

146 }

147 

148 void dfs(int t)

149 {

150    int i;

151    for(i=k[t];i!=-1;i=edge[i].next)

152     {

153       if(edge[i].vis==0)

154        {

155          edge[i].vis=1;

156          dfs(edge[i].e);

157          stack[st++]=edge[i].id;//单词ID是以  单词的末尾字母存的 所以提取末尾获得单词ID 

158        }//同一个起点可能引出多条边 从这个点用一个单词(一条边)得到一个新的起点此时从新起点开始  

159     }//     以上从一个起点选边都是 选这个起点 最小的边(注意以上排序) 

160 }

161 

162 int main()

163 {

164    int i,iscase;

165    scanf("%d",&iscase);

166    while(iscase--)

167     {

168       scanf("%d",&M);

169       init();

170       int t=start();

171       if(-1==t)printf("***\n");

172       else

173        {

174           dfs(t);

175           printf("%s",cha[stack[st-1]].ch);

176           for(i=st-2; i>=0;--i)

177            printf(".%s",cha[stack[i]].ch);

178           printf("\n");              

179        }

180     }

181    return 0;

182 }

 

你可能感兴趣的:(poj)