题目大意:给你一个n个点m条无向边的图,问这个图是否能够:
1,被四染色(用四种颜色给图染色,且相邻点颜色不同)。
2,找出一个奇环,满足在原图中去掉这个奇环后每个点依然相邻。
请输出1或者2中的任意一种,如果不能就输出类似-1的东西。
数据范围:n,m≤300000
xfzIQ=-1
我们首先构造一棵生成树出来,这个生成树显然是一个二分图,二分图显然可以黑白染色。
对于原图中的非树边,我们把这些变构成一个图G,若G为二分图,显然原图就可以四染色了。
若G不是二分图,那么G中必有奇环,我们把奇环找出来输出就可以了。
智商被侮辱系列题目。
#include<bits/stdc++.h>
#define M 300005
using namespace std; int f[M]={}; int get(int x){return f[x]==x?x:f[x]=get(f[x]);}
struct edge{int u,next;}e[M*]={}; int head[M]={},use=;
void add(int x,int y){use++;e[use].u=y;e[use].next=head[x];head[x]=use;} int col1[M]={},col2[M]={};
int n,m,noX=,noY=;
int u[M]={},v[M]={},sel[M]={}; void dfs(int x,int col){
col1[x]=col; if(col==) col=; else col=;
for(int i=head[x];i;i=e[i].next)
if(col1[e[i].u]==) dfs(e[i].u,col);
}
void dfs2(int x,int col){
col2[x]=col; if(col==) col=; else col=;
for(int i=head[x];i;i=e[i].next)
if(col2[e[i].u]==) dfs2(e[i].u,col);
else{
if(col2[e[i].u]==col2[x]){
noX=e[i].u;
noY=x;
//return;
}
}
} int ans[M]={},cnt=;
int getans(int x,int fa){
if(x==noY){
ans[++cnt]=x;
return ;
}
for(int i=head[x];i;i=e[i].next) if(e[i].u!=fa){
if(getans(e[i].u,x)){
ans[++cnt]=x;
return ;
}
}
return ;
} int main(){
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++) f[i]=i;
for(int i=;i<=m;i++){
scanf("%d%d",u+i,v+i);
int U=get(u[i]),V=get(v[i]);
if(U==V) continue;
sel[i]=; f[U]=V;
add(u[i],v[i]); add(v[i],u[i]);
}
dfs(,);
memset(head,,sizeof(head)); use=;
for(int i=;i<=m;i++) if(sel[i]==){
add(u[i],v[i]); add(v[i],u[i]);
}
for(int i=;i<=n;i++)
if(col2[i]==) dfs2(i,); if(noX==){
printf("A ");
for(int i=;i<=n;i++)
printf("%d ",col1[i]+(col2[i]-)*);
return ;
} memset(head,,sizeof(head)); use=;
for(int i=;i<=n;i++) f[i]=i;
for(int i=;i<=m;i++) if(sel[i]==){
if(col2[u[i]]==col2[v[i]]) continue;
int U=get(u[i]),V=get(v[i]);
if(U==V) continue;
f[U]=V;
add(u[i],v[i]); add(v[i],u[i]);
if(get(noX)==get(noY)) break;
}
getans(noX,);
printf("B %d ",cnt);
for(int i=;i<=cnt;i++) printf("%d ",ans[i]);
}