11.23A组 T1----walk(欧拉路径)
Solution
合法的图至少满足有0个/2个度数为奇数的点----即图有欧拉通路
当所有点度数为偶数,则图上所有环包含起始点,
若有合法的起始点,显然度数最大的点可以作为起始点,
则把起始点从图中删去,图中不存在环,O(n)判定。
当有两个点A、B的度数为奇数,则A、B中有一点为起始点,
连接A、B,则可以转化为点度数全为偶数的情况。
Review
考察了图的欧拉路径的相关知识。
考场发现了两种情况的相互转化关系后,就死磕有两个点度数为奇数的情况怎么快速判定,然后,,就“磕死”了。
code
#include<cstdio>
#define N 100005
using namespace std;
inline int read()
{
int x=0;char ch=getchar();
while (ch<'0'||ch>'9')ch=getchar();
while (ch>='0'&&ch<='9')x=x*10+(ch^48),ch=getchar();
return x;
}
int T,n,m;
int d[N],sum,A,B;
int lk[N];
struct edge{
int to,nx;
}e[N*4];int tot;
inline void add(int u,int v)
{
++d[u];++d[v];
e[++tot].to=v;e[tot].nx=lk[u];lk[u]=tot;
e[++tot].to=u;e[tot].nx=lk[v];lk[v]=tot;
}
bool vis[N],bz;
inline void dfs(int x,int las)
{
if (x==A)return;
if (vis[x])
{
bz=1;
return;
}
vis[x]=1;
for (int i=lk[x];i;i=e[i].nx)
if (e[i].to!=las)
{
dfs(e[i].to,x);
if (bz)return;
}
}
inline void check()
{
for (int i=1;i<=n;++i)vis[i]=0;
bz=0;
for (int i=1;i<=n&&!bz;++i)
if (!vis[i]&&i!=A)dfs(i,0);
puts(bz?"NO":"YES");
}
int main()
{
freopen("walk.in","r",stdin);
freopen("walk.out","w",stdout);
T=read();
while (T--)
{
n=read();m=read();
for (int i=1;i<=n;++i)d[i]=lk[i]=0;sum=tot=0;
for (int i=1;i<=m;++i)add(read(),read());
A=B=0;
for (int i=1;i<=n;++i)
if (d[i]&1)++sum,A?B=i:A=i;
if (sum!=0&&sum!=2)puts("NO");
else
{
if (sum==2)
{
add(A,B);
if (d[A]<d[B])A^=B^=A^=B;
bz=0;
for (int i=1;i<=n;++i)
if (d[i]>d[A])
{
puts("NO");
bz=1;
break;
}
if (bz)continue;
check();
}else
{
for (int i=1;i<=n;++i)
if (d[i]>d[A])A=i;
check();
}
}
}
return 0;
}
}else
{
for (int i=1;i<=n;++i)
if (d[i]>d[A])A=i;
check();
}
}
}
return 0;
}