题意:给你N个房间以及房间之间的门,且给你初始的房间号M,问你从初始房间走,可不可以经过每个门仅1次,最后到达0号房间.且所有的门都被你走过1次?
思路:将房间当成顶点,门作为边,转化为判断无向图是否存在欧拉回路或者通路。
所有门都被走一遍,所以任何有门的房间都必须是在同一连通分量:即degree不为0的节点所属并查集唯一.(因为允许存在孤立的一点,房间)
第二,如果所有点的degree都为偶数,那么该图的连通部分存在欧拉回路.(最终要求在0点结束)所以此时要求M也为0,否则不可能在0结束.
第三,如果所有点中有2个点的degree为奇数,要求这两个点一个为0,一个为M.否则不存在欧拉通路.
至于当存在欧拉路时,从M需要走多少条边到0房间呢?肯定是走过所有的边了,所有边数==总度数/2.
#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <map>
#include <string>
#include <set>
#include <ctime>
#include <cmath>
#include <cctype>
using namespace std;
#define maxn 100
#define LL long long
int cas=1,T;
int n,m;
int sum;
int degree[maxn];
int pre[maxn];
int Find(int x)
{
return pre[x]==-1?x:pre[x]=Find(pre[x]);
}
int main()
{
char str[200];
while (scanf("%s",str) && str[0]=='S')
{
sum=0;
memset(pre,-1,sizeof(pre));
memset(degree,0,sizeof(degree));
scanf("%d%d",&m,&n);
getchar();
for (int i = 0;i<n;i++)
{
gets(str);
int len = strlen(str);
if (len==0)
continue;
int num = 0;
for (int j = 0;j<=len;j++)
{
if (str[j]==' ' || str[j]==0)
{
degree[num]++;
degree[i]++;
sum+=2;
if (Find(i)!=Find(num))
{
pre[Find(i)]=Find(num);
}
num=0;
}
else
num=num*10+str[j]-'0';
}
}
gets(str);
if (Find(0)!=Find(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;
}
cnt=0;
for (int i = 0;i<n;i++)
cnt+=degree[i]%2==1 ? 1:0;
if (cnt==0 && m==0)
printf("YES %d\n",sum/2);
else if (cnt==2 && m!=0 && degree[0]%2==1 && degree[m]%2==1)
printf("YES %d\n",sum/2);
else
printf("NO\n");
}
//freopen("in","r",stdin);
//scanf("%d",&T);
//printf("time=%.3lf",(double)clock()/CLOCKS_PER_SEC);
return 0;
}