列表

详情


NC51313. Planar

描述

若能将无向图 G=(V, E) 画在平面上使得任意两条无重合顶点的边不相交,则称 G 是平面图。判定一个图是否为平面图的问题是图论中的一个重要问题。现在假设你要判定的是一类特殊的图,图中存在一个包含所有顶点的环,即存在哈密顿回路。

输入描述

输入文件的第一行是一个正整数 T,表示数据组数 (每组数据描述一个需要判定的图)。接下来从输入文件第二行开始有 T 组数据,每组数据的第一行是用空格隔开的两个正整数 N 和 M,分别表示对应图的顶点数和边数。紧接着的 M 行,每行是用空格隔开的两个正整数 u 和 v ,表示对应图的一条边 , 输入的数据保证所有边仅出现一次。每组数据的最后一行是用空格隔开的 N 个正整数,从左到右表示对应图中的一个哈密顿回路:,即对任意  且对任意 。输入的数据保证  的数据满足 

输出描述

包含 T 行,若输入文件的第 i 组数据所对应图是平面图,则在第 i 行输出 ,否则在第 i 行输出 ,注意均为大写字母

示例1

输入:

2
6 9
1 4
1 5
1 6
2 4
2 5
2 6
3 4
3 5
3 6
1 4 2 5 3 6
5 5
1 2
2 3
3 4
4 5
5 1
1 2 3 4 5

输出:

NO
YES

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++ 解法, 执行用时: 19ms, 内存消耗: 828K, 提交时间: 2021-10-15 22:43:11

#include<bits/stdc++.h>
using namespace std;
struct Node
{
  int next,to;
}edge[100001];
struct Edge
{
  int u,v;
}e[20001];
int head[1001],num,n,m,id[1001],cnt;
int vis[1001];
void add(int u,int v)
{
  num++;
  edge[num].next=head[u];
  head[u]=num;
  edge[num].to=v;
}
bool dfs(int x,int pa,int k)
{int i;
  vis[x]=k^1;
  for (i=head[x];i;i=edge[i].next)
    {
      int v=edge[i].to;
      if (vis[v]==-1)
    {
      if (!dfs(v,x,k^1)) return 0;
    }
      else
    {
      if (vis[v]==(k^1))
        return 0;
    }
    }
  return 1;
}
int main()
{int T,i,j,x;
  cin>>T;
  while (T--)
    {
      cin>>n>>m;
      for (i=1;i<=m;i++)
    {
      scanf("%d%d",&e[i].u,&e[i].v);
    }
      memset(id,0,sizeof(id));
      for (i=1;i<=n;i++)
    {
      scanf("%d",&x);
      id[x]=i;
    }
      if (m>3*n-6)
    {
      printf("NO\n");
      continue;
    }
      num=0;
      memset(head,0,sizeof(head));
      for (i=1;i<=m;i++)
    {
      int u=e[i].u,v=e[i].v;
      if (id[u]>id[v]) swap(u,v);
      for (j=1;j<i;j++)
        {
          int p=e[j].u,q=e[j].v;
          if (id[p]>id[q]) swap(p,q);
          if (id[u]<id[p]&&id[v]<id[q]&&id[p]<id[v]) add(i,j),add(j,i);
          if (id[p]<id[u]&&id[q]<id[v]&&id[u]<id[q]) add(i,j),add(j,i);
        }
    }
      memset(vis,-1,sizeof(vis));
      for (i=1;i<=m;i++)
    if (vis[i]==-1)
    {
      if (!dfs(i,0,0)) break;
    }
      if (i>m) printf("YES\n");
      else printf("NO\n");
    }
     return 0;
}

C++(g++ 7.5.0) 解法, 执行用时: 22ms, 内存消耗: 792K, 提交时间: 2022-08-22 11:24:19

#include<bits/stdc++.h>
using namespace std;
struct Node
{
  int next,to;
}edge[100001];
struct Edge
{
  int u,v;
}e[20001];
int head[1001],num,n,m,id[1001],cnt;
int vis[1001];
void add(int u,int v)
{
  num++;
  edge[num].next=head[u];
  head[u]=num;
  edge[num].to=v;
}
bool dfs(int x,int pa,int k)
{int i;
  vis[x]=k^1;
  for (i=head[x];i;i=edge[i].next)
    {
      int v=edge[i].to;
      if (vis[v]==-1)
    {
      if (!dfs(v,x,k^1)) return 0;
    }
      else
    {
      if (vis[v]==(k^1))
        return 0;
    }
    }
  return 1;
}
int main()
{int T,i,j,x;
  cin>>T;
  while (T--)
    {
      cin>>n>>m;
      for (i=1;i<=m;i++)
    {
      scanf("%d%d",&e[i].u,&e[i].v);
    }
      memset(id,0,sizeof(id));
      for (i=1;i<=n;i++)
    {
      scanf("%d",&x);
      id[x]=i;
    }
      if (m>3*n-6)
    {
      printf("NO\n");
      continue;
    }
      num=0;
      memset(head,0,sizeof(head));
      for (i=1;i<=m;i++)
    {
      int u=e[i].u,v=e[i].v;
      if (id[u]>id[v]) swap(u,v);
      for (j=1;j<i;j++)
        {
          int p=e[j].u,q=e[j].v;
          if (id[p]>id[q]) swap(p,q);
          if (id[u]<id[p]&&id[v]<id[q]&&id[p]<id[v]) add(i,j),add(j,i);
          if (id[p]<id[u]&&id[q]<id[v]&&id[u]<id[q]) add(i,j),add(j,i);
        }
    }
      memset(vis,-1,sizeof(vis));
      for (i=1;i<=m;i++)
    if (vis[i]==-1)
    {
      if (!dfs(i,0,0)) break;
    }
      if (i>m) printf("YES\n");
      else printf("NO\n");
    }
}

上一题