0
点赞
收藏
分享

微信扫一扫

POJ 1300 Door Man (无向图欧拉通路和回路的判定+并查集)


Door Man

Description

You are a butler in a large mansion. This mansion has so many rooms that they are merely referred to by number (room 0, 1, 2, 3, etc...). Your master is a particularly absent-minded lout and continually leaves doors open throughout a particular floor of the house. Over the years, you have mastered the art of traveling in a single path through the sloppy rooms and closing the doors behind you. Your biggest problem is determining whether it is possible to find a path through the sloppy rooms where you: 

 

  1. Always shut open doors behind you immediately after passing through 
  2. Never open a closed door 
  3. End up in your chambers (room 0) with all doors closed 

In this problem, you are given a list of rooms and open doors between them (along with a starting room). It is not needed to determine a route, only if one is possible. 

Input

Input to this problem will consist of a (non-empty) series of up to 100 data sets. Each data set will be formatted according to the following description, and there will be no blank lines separating data sets. 
A single data set has 3 components: 

 

  1. Start line - A single line, "START M N", where M indicates the butler's starting room, and N indicates the number of rooms in the house (1 <= N <= 20). 
  2. Room list - A series of N lines. Each line lists, for a single room, every open door that leads to a room of higher number. For example, if room 3 had open doors to rooms 1, 5, and 7, the line for room 3 would read "5 7". The first line in the list represents room 0. The second line represents room 1, and so on until the last line, which represents room (N - 1). It is possible for lines to be empty (in particular, the last line will always be empty since it is the highest numbered room). On each line, the adjacent rooms are always listed in ascending order. It is possible for rooms to be connected by multiple doors! 
  3. End line - A single line, "END" 

Following the final data set will be a single line, "ENDOFINPUT". 

Note that there will be no more than 100 doors in any single data set.

Output

For each data set, there will be exactly one line of output. If it is possible for the butler (by following the rules in the introduction) to walk into his chambers and close the final open door behind him, print a line "YES X", where X is the number of doors he closed. Otherwise, print "NO".

Sample Input


START 1 2


1


 


END


START 0 5


1 2 2 3 3 4 4


 


 


 


 


END


START 0 10


1 9


2


3


4


5


6


7


8


9


 


END


ENDOFINPUT


Sample Output


YES 1


NO


YES 10


Source

South Central USA 2002

Time Limit: 1000MS

 

Memory Limit: 10000K

Total Submissions: 3284

 

Accepted: 1368

题意

给出一些房间和房间上的门以及房间之间的路径,如果你沿着这条路走到另一个房间,那么就得关掉这条路上的门,关掉的门不能再打开,问能不能从m号房间,在关掉所有门之后刚好走到房间0。

分析

比较裸的欧拉路径问题;

第一,存在一个欧拉回路,且m==0

第二,存在一个欧拉通路,且m和0为终点起点

不过,有一个坑点,就是这个题连通性的问题

如果,你不考虑连通性的问题,ok,这个题就过了,数据弱,

但是,如果考虑了连通性的问题,你就可能wa到死,这题可以有独立点存在,就是某一个房间可以没有门,所以判断连通性时候只需要判断有门的,即degree[i]不为0的

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<math.h>
#include<set>
#include<vector>
#include<sstream>
#include<queue>
#define ll long long
#define PI 3.1415926535897932384626
#define inf 0x3f3f3f3f
#define N 1000
 
using namespace std;
 
int n, start,sum;//sum总度数
int f[N],degree[N];//记录第i点的度数
 
void init()
{
	for (int i = 0; i <= n; i++)
		f[i] = i;
	sum=0;
	memset(degree,0,sizeof(degree));
}
int find(int x)
{
	return x == f[x] ? x : f[x] = find(f[x]);
}
void merge(int x, int y)
{
	int t1, t2;
	t1 = find(x); t2 = find(y);
	if (t1 != t2)	f[t2] = t1;
	else return;
}
///判断是否是欧拉路径(保证连通的情况下)
///0:不存在
///1:欧拉通路
///2:欧拉回路
int isEuler()  ///注意:编号从0开始
{
	    int cnt=0;//记录奇数度的点个数
        for(int i=0;i<n;i++) 
        	cnt += degree[i]%2==1 ? 1:0;
		
        if(cnt==0 )//欧拉回路
          return 2;
        else if(cnt==2)//欧拉通路
            return 1;
        else  
           return 0;
}
int isconnect()
{
	int cnt = 0;
	for (int i =0;i <n; i++)
	{
		if (f[i] == i)
			cnt++;
	}
	 
	if (cnt <=1)	return 1;
	else return 0;
}
int main()
{
	char str[200];
    while(scanf("%s",str)==1&& str[0]=='S')
    {
        init();
 
        scanf("%d%d",&start,&n);//处理输入
        getchar();//读回车
        
        for(int i=0;i<n;i++)
        {
            gets(str);
            int len=strlen(str);
            if(len==0) continue;
            int num=0;//读取当前str中的数
            for(int j=0;j<=len;j++)
            {
                if(str[j]==' '||str[j]==0)//说明之前已经读了一个数在num中
                {
                    degree[num]++;
                    degree[i]++;
                    sum+=2;
                    merge(num,i);
                    num=0;
                }
                else
                {
                    num = num*10+str[j]-'0';
                }
            }
        }
        gets(str);//读入末尾的END
 
        if(find(0)!=find(start))//0点与m点不通
        {
            printf("NO\n");
            continue;
        }
        int cnt=0;//只能有一个连通分量
        for(int i=0;i<n;i++)
        	if(degree[i])
            cnt += find(i)==i?1:0;
        if(cnt>1)
        {
            printf("NO\n");
            continue;
        }
        
        
		int flag=isEuler();
        if(flag==2 && start==0)//欧拉回路,且终点是本身
            printf("YES %d\n",sum/2);
        else if(flag==1 && start!=0 && degree[0]%2==1 && degree[start]%2==1)//欧拉通路,判断start和0是否为起点和终点
            printf("YES %d\n",sum/2);
        else//其他非法情况
            printf("NO\n");
    }
    return 0;
	
}

 

举报

相关推荐

0 条评论