Colored Sticks --欧拉回路,并查集,字典树,

You are given a bunch of wooden sticks. Each endpoint of each stick is colored with some color. Is it possible to align the sticks in a straight line such that the colors of the endpoints that touch are of the same color?
Input
Input is a sequence of lines, each line contains two words, separated by spaces, giving the colors of the endpoints of one stick. A word is a sequence of lowercase letters no longer than 10 characters. There is no more than 250000 sticks.
Output
If the sticks can be aligned in the desired way, output a single line saying Possible, otherwise output Impossible.
Sample Input
blue red
red violet
cyan blue
blue magenta
magenta cyan
Sample Output
Possible
Hint

Huge input,scanf is recommended.

分析:经典的欧拉回路问题。。。,每次只经过一条边且仅一次


具体见代码:

/* 欧拉回路:
 *  ①图是连通图
 *  ②只有偶数度顶点或者只有两个奇度顶点
 *  这道题实质就是判断是否能构成一个欧拉回路
 *  连通性可以通过并查集来判断
 *  顶点度数的统计可以结合字典树来统计
 *  使用字典树可以统计颜色的种类
 * */
import java.util.*;
public  class Main{
   static Scanner in = new Scanner(System.in);
   static int[] f = new int[500010];
   static int[] degree = new int[500010];
   //寻找根节点
   static int find(int x){
	   if(f[x]==-1)
		   return x;
	   else
		   return f[x] = find(f[x]);
   }
   //合并集合
   static void merge(int a,int b){
	   int t1 = find(a);
	   int t2 = find(b);
	   if(t1!=t2)
		   f[t1]=t2;//往右合并
   }
   public static void main(String args[]){ 
	   //初始化
	   Arrays.fill(f, -1);
	   Arrays.fill(degree, 0);
	   TrieNode root  = new TrieNode();  
       int k = in.nextInt();
       String s1;String s2;
       int a,b;
       while(k-->0) {
		   s1 = in.next();
		   s2 = in.next();
		  a = root.insert(root, s1);
		  b = root.insert(root, s2);
//		  System.out.println(a+" "+b);
		  //维护度数数组
		   degree[a]++;
		   degree[b]++;
		  merge(a, b);
	   }
     int color = root.color;
     int cnt1 =0 ,cnt2=0;
     for (int i = 0; i < color; i++) {
		 if(f[i]==-1) cnt1++;//根节点数目
		 if(degree[i]%2==1) cnt2++;//奇数度顶点数目
		 if(cnt1>1) break;
		 if(cnt2>2) break;
	  }
     //cnt1==0木棒的数目可能为零
     if((cnt1==0||cnt1==1)&&(cnt2==0||cnt2==2))
    	 System.out.println("Possible");
     else
    	 System.out.println("Impossible");
   }    
}
//字典树节点  
class TrieNode{  
   static int size = 26;//字符的种类,即每个节点的孩子数目  
   static int color = 0;  
   
    int id;//每种颜色的ID 
    TrieNode[] son; 
    boolean isEnd;
      
    TrieNode() {  
        id = 0;  
        son = new TrieNode[size];
        isEnd = false;
     }  
     int insert(TrieNode root,String str){   
    	 
         TrieNode p = root;//每次从根节点开始  
         int len=str.length();  
        for(int i=0; i<len; i++){    
               
            if(p.son[str.charAt(i)-'a']==null){    
                p.son[str.charAt(i)-'a']=new TrieNode();    
            }    
            p=p.son[str.charAt(i)-'a']; //字符串每个字符向下一层             
       } 
        //是否到了一个颜色的结束
        if(p.isEnd){
        	return p.id;
        }
        else{
         p.isEnd = true;
         p.id = color++;
         return p.id;  
        }
     }  
}

字典树存储效率比较高。。。。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值