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:
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.
Following the final data set will be a single line, "ENDOFINPUT". 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
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;
}