uva10129

思路:明显的有向联通图,关键是判断是否存在欧拉道路

题目只是要求输出是否可能,不要求输出排序结果

要判断有向图的欧拉道路,首先要判断它的基图,也就是没有方向是否的图,是否联通,

如果联通,再判断输入输出度数

对于欧拉回路,要求苛刻一点,所有点的入度都要等于出度,那么就存在欧拉回路了
 对于欧拉道路,要求松一点,只有一个点,出度比入度大1,这个点一定是起点; 一个点,入度比出度大1,这个点一定是终点.其余点的出度等于入度

网上很多思路都非常乱,我们还是按照传统的一步一步来,用dfs()统计图是否联通

package test;

import java.util.Arrays;
import java.util.Scanner;


public class Test{	
	static Scanner sc = new Scanner(System.in);
	static String line;
	
	static int n = 26;//26个字母
	/*
	 * 有向图,代表一个单词开头指向结尾n->n,因为我们要借用无向图来判断是否联通,所以存储了a->b以后,还有存储b->a,从而使有向转换为无向
	 */
	static int[][] G = new int[n][n];
	static boolean[] vis = new boolean[n];//记录26个字母是否联通
	static int[] in = new int[n];//记录入度
	static int[] out = new int[n];//记录出度
	
	/**
	 * 将字符转换成对应数字
	 * @param c
	 * @return
	 */
	static int char_int(char c){
		return c-'a';
	}		
	
	/**
	 * 使用dfs,设置vis数组,用于后面检验26个字母是否联通(也就是图是否联通)
	 * @param u
	 */
	static void euler(int u){
		vis[u] = true;
		for(int v=0;v<n;v++){
			if(G[u][v]>0){
				G[u][v]--;//以为当成无向图看待,其实就是两个有向图,所以要去除两个方向
				G[v][u]--;//
				euler(v);				
			}
		}
	}
	
	/**
	 * 检查vis数组,判断图是否联通
	 * @return
	 */
	static boolean checkDfs(){
		for (int u = 0; u < n; u++) {  
	        if (in[u] + out[u]>0) {  
	            if (vis[u] == false) {  
	                return false;  
	            }  
	        }  
	    }  	  
	    return true;  
	}
	
	/**
	 * 检查出入度是否符合规则
	 * @return
	 */
	static boolean checkDeg(){
		boolean flag=true;
		int num1=0,num2=0;
		for(int i=0;i<n;i++){
			if(!flag) break;
            if(in[i]!=out[i]){
                if(in[i]==out[i]+1) { ++num1; }
                else if(out[i]==in[i]+1) { ++num2; }
                else {flag=false; break; }
            }
		}
		
		if(num1>=1 && num2>=1 && num1+num2>2) flag=false;
		return flag;
	}
	
	public static void main(String[] args) {
		/*
		 * 输入
		 */
		while(!"".equals((line=sc.nextLine()))){
			G[char_int(line.charAt(0))][char_int(line.charAt(line.length()-1))]++;
			G[char_int(line.charAt(line.length()-1))][char_int(line.charAt(0))]++;
			in[char_int(line.charAt(0))]++;
			out[char_int(line.charAt(line.length()-1))]++;
		}
		
		Arrays.fill(vis, false);
		euler(0);		
		if(checkDfs() && checkDeg()){
			System.out.println("成功");
		}else{
			System.out.println("失败");
		}
		
	}
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值