列表

详情


NC19791. Graph Coloring II

描述

修修在黑板上画了一些无向连通图,他发现他可以将这些图的结点用三种颜色染色,满足相邻点不同色。
澜澜不服气,在黑板上画了一个四个点的完全图。修修跟澜澜说,这个图我能找到一个简单奇环,并且删掉这个环上的边之后图仍然联通。
澜澜又在黑板上画了一个n个点m条边的无向连通图。很可惜这不是一道数数题,修修做不出来了。
澜澜非常得意,作为一位毒瘤出题人,有了好题当然要跟大家分享,于是他把这道题出给你做了。

输入描述

第一行两个整数n,m (1≤ n,m≤ 3*105),接下来m行每行两个整数ai,bi表示一条边 (1≤ ai,bi≤ n)。
保证图连通,并且不存在重边和自环。

输出描述

如果你能把图三染色,第一行输出0,第二行输出n个整数表示每个点的颜色 (0≤ xi≤ 2)。如果有多种合法方案,你可以输出任意一种。
如果你能找到一个删去其中的边后图仍然联通的简单奇环,第一行输出环长k,第二行输出k个整数表示环上结点编号 (1≤ yi≤ n),你需要保证yi和yi+1之间有边,y1和yn之间有边。如果有多种合法方案,你可以输出任意一种。
如果两种情况都是可行的,你可以输出任意一种。
如果两种情况都是不可行的,请输出一行一个整数-1。

示例1

输入:

3 3
1 2
1 3
2 3

输出:

0
0 1 2

示例2

输入:

4 6
1 2
1 3
1 4
2 3
2 4
3 4

输出:

3
1 2 3

原站题解

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

C++ 解法, 执行用时: 307ms, 内存消耗: 18992K, 提交时间: 2021-09-26 00:07:12

#include<bits/stdc++.h>
using namespace std;
const int maxn = 3e5+100;
vector<int> G[maxn];
int color[maxn];
int n,m;
queue<int> que;
void bfs()
{
  que.push(1);
  while (!que.empty())
  {
    int u = que.front();
    que.pop();
    if (color[u]!=0)continue;
    color[u]=1;
    for (int v:G[u])color[v]=2;
    for (int v:G[u])for (int vv:G[v])if (!color[vv])
    {
      que.push(vv);
    }
  }
}
bool used[maxn];
vector<int> stak;
void dfs(int u)
{
  used[u]=1;
  stak.push_back(u);
  for (int v:G[u])if (color[v]!=1)
  {
    if (used[v]&&color[v]==color[u])
    {
      vector<int> res;
      while (true)
      {
        res.push_back(stak.back());
        if (res.back()==v)break;
        stak.pop_back();
      }
      printf("%d\n",(int)res.size());
      for (int num:res)printf("%d ",num);
      exit(0);
    }
    if (!used[v])
    {
      if (color[u]==2)color[v]=0;
      else color[v]=2;
      dfs(v);
    }
  }stak.pop_back();
}
int main()
{
  scanf("%d %d",&n,&m);
  for (int i=1,u,v;i<=m;++i)
  {
    scanf("%d %d",&u,&v);
    G[u].push_back(v);
    G[v].push_back(u);
  }
  bfs();
  for (int i=1;i<=n;++i)if (!used[i]&&color[i]==2)
  {
    dfs(i);
  }
  printf("0\n");
  for (int i=1;i<=n;++i)printf("%d ",color[i]);
}

上一题