HDU 1116

这个题目要运用到欧拉路得相关知识,并且也要并查集,题目说的是:给你n个单词,要你判断这些单词能不能首尾相连。理解题目意思后,进行转化,输入字符串,提取首位字母作为下标来表示两节点的出现,以及相对应节点入度和出度的增加,转化为并查集的应用即可。那么从可以想象一幅由首位字母节点构成的图,当且仅当图是一条欧拉回路或者欧拉通路的时候,才能满足题目的要求,至于欧拉回路和欧拉通路的判定可以总结为如下:
1)所有的点联通
2)欧拉回路中所有点的入度和出度一样。

3)欧拉通路中起点的入度 - 出度 = 1,终点的 初度 - 入度 = 1, 其他的所有点入度 = 出度;

无向图存在欧拉回路条件

  一个无向图存在欧拉回路,当且仅当该图所有顶点度数都是偶数。

有向图存在欧拉回路条件

  一个有向图存在欧拉回路,且所有顶点的入度等于出度


 #include<stdio.h>   
 #include<string.h>   
 #include<math.h>   
 #define N 30   
 int father[N],vis[N];  
 //father[i] 表示节点 i 的 BOSS ! vis[i]表示节点 i 出现过 
 int findx(int x)  
 {  //找节点  x 的 BOSS ! 
     if(father[x]!=x)  
         father[x]=findx(father[x]);  
     return father[x];  
 }  
 void merge(int a,int b)  
 {  // 合并 节点 a 和节点 b
     int x,y;  
     x=findx(a);  
     y=findx(b);  
     if(x!=y) father[x]=y;  
 }  
 int main()  
 {  
     int text,cnt,i,j,n,out[N],in[N],p[30],a,b;  
     char str[1001];  
     scanf("%d",&text);  
     while(text--)  
     {  
         scanf("%d",&n);  
         memset(out,0,sizeof(out));  
         memset(in,0,sizeof(in));  
         memset(vis,0,sizeof(vis));  
         for(i=0;i<26;i++)  
             father[i]=i;  //初始化数组 
         while(n--)  
         {  // 处理所给信息 ! 
             scanf("%s",str);  
             a=str[0]-'a';  
             b=str[strlen(str)-1]-'a';  
             merge(a,b);  
             out[a]++;  
             in[b]++;  // 记录节点 a 和 b的入度和出度 
             vis[a]=1;  
             vis[b]=1; //标记节点 a 和 b的出现 
         }  
         for(i=0;i<26;i++)  
             father[i]=findx(i);  //找出每个节点的 BOSS  
         for(cnt=0,i=0;i<26;i++)  
             if(vis[i] && father[i]==i)  
                 cnt++;  // 统计最终 BOSS 即根节点的个数 。 
         if(cnt>1)  //图不连通   
         {  
             printf("The door cannot be opened.\n");  
             continue;  
         }  
           
         for(j=0,i=0;i<26;i++)  
             if(vis[i] && out[i]!=in[i])  
                 p[j++]=i;  //统计入度和出度不相等的点的信息 
         if(j==0)   
         {//欧拉回路,即环   
             printf("Ordering is possible.\n");  
             continue;  
         }  
         if(j==2 && ( 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 ) )  
         {//欧拉通路   
             printf("Ordering is possible.\n");  
             continue;  
         }  
         printf("The door cannot be opened.\n");  
     }  
     return 0;  
 }  


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值