POJ 1386(欧拉回路,欧拉通路,变相DNF)

/*
	此题用了我一天,说明我的基础知府还是不够扎实;
	
	考点:
		欧拉回路和欧拉通路, 加变相DNF;
		前提:要是连通图;(用dnf,(每一步两头搜)) 
		欧拉回路,要求图的每一个点的出度和入度一样,
		欧拉通路,要求图的起点的出度比入度大1,终点的出度比入度少于1; 
*/
#include <iostream>
#include <fstream>
#include <cstring>
using namespace std;
const int MAX = 26;
int map[MAX][MAX];
int visit_in[MAX];
int visit_out[MAX];
int flag[MAX];
int M;
char str[1005];
void down(int n);
//图的遍历,向上搜 
void up(int sa){
	flag[sa] = 0;
	for(int i=0; i<26; ++i){
		if(map[i][sa] > 0){			
			--map[i][sa];
			up(i);
			down(sa);
		}
	}	
}
//图的遍历,向下搜 
void down(int sb){
	flag[sb] = 0;
	for(int i=0; i<26; ++i){
		if(map[sb][i] > 0){
			--map[sb][i];
			up(i);
			down(i);
		}
	}
}
int main(){		
	int T;
	int a,b,len,sa,sb;
	scanf("%d",&T);
	while(T--){		
		memset(visit_in, 0, sizeof(visit_in));
		memset(visit_out, 0, sizeof(visit_out));
		memset(map, 0, sizeof(map));
		memset(flag, 0, sizeof(flag));
		scanf("%d",&M);
		//转成邻接矩阵 
		int num = M;
			scanf("%s",str);
			len = strlen(str);
			sa = a = str[0]-97;
			sb = b = str[len-1]-97;
			flag[a] = flag[b] = 1;
			++visit_out[a];
			++visit_in[b];
			++map[a][b];
		while(--num){
			scanf("%s",str);
			len = strlen(str);
			a = str[0]-97;
			b = str[len-1]-97;
			flag[a] = flag[b] = 1;
			++visit_out[a];
			++visit_in[b];
			++map[a][b];			
		}
		//用第一个点开始遍历; 
		--map[sa][sb];
		up(sa);
		down(sb);
		//判断有点或边没有遍历完的 
		int res = 0;
		for(int i=0; i<26; ++i){
			if(flag[i] == 1){
				res = 1;
				break;
			}
		}
		for(int i=0; (i<26) && (res==0); ++i){
			for(int j=0; j<26; ++j){
				if(map[i][j]){
					res = 1;
					break;
				}
			}
		}		
		if(res == 1){
			printf("The door cannot be opened.\n");
			continue ;
		}
		//判断点的出度和入度是否符合要求; 
		res = 0;
		a = b = 0;
		for(int i=0; i<26; ++i){
			if(visit_out[i] != visit_in[i]){
				res++;
				if( ( visit_out[i] > visit_in[i] ) && (visit_out[i] - visit_in[i] == 1) )
					a = 1;
				if( ( visit_out[i] < visit_in[i] ) && (visit_in[i] - visit_out[i] == 1) )
					b= 1;				
			}
		}
		if(res == 0 || (res == 2 && a == 1 && b==1 )){
			printf("Ordering is possible.\n");
		}else{
			printf("The door cannot be opened.\n");
		}						
	}
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值