思路
无非就两种情况:可二涂色或者存在奇环。
那么我们在dfs的过程中留意有无涂色不符的情况,
没有发现就直接输出一种涂色方案就行了。
现在问题就是找到奇环该怎么输出呢?
因为我是个笨比所以一开始写了个tarjan记录SCC,
然后去输出第一个奇数并大于1个点的SCC的每一个点编号,
结果只过了45.45%(所以看代码的时候请忽略没删的多余变量吧)
实际上我们对一个点访问第二次的时候发现它涂色不符,就
可以确定我们前面遍历了一个环,而这个环就是奇环,并且在栈中是连续的。
我们只需要按照入栈顺序进行输出即可。(写了tarjan还是有所启发的)
代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=300007;
int n,m,u,v,flag;
int head[maxn],cnt;
int col[maxn],vis[maxn];
int dfn[maxn],low[maxn],sz[maxn],bel[maxn];
int stk[maxn],top,idx,sccnum;
vector<int>scc[maxn];
struct E{
int next,to;
}e[maxn<<1];
void addedge(int from,int to){
e[++cnt].next=head[from];
e[cnt].to=to;
head[from]=cnt;
}
void dfs(int x,int fa,bool c){
if(dfn[x]){ //已经访问过该节点
if(dfn[x]<top&&col[x]!=c){ //如果在栈中并且颜色不符
printf("%d\n",top-dfn[x]+1);
for(int i=dfn[x];i<=top;i++) printf("%d ",stk[i]);
exit(0);
}
return;
}
stk[++top]=x,dfn[x]=top; //入栈,用桶存栈下标
col[x]=c;
for(int i=head[x];i;i=e[i].next){
if(e[i].to!=fa){
dfs(e[i].to,x,!c);
}
}
--top;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n>>m;
for(int i=1;i<=m;i++){
cin>>u>>v;
addedge(u,v);
addedge(v,u);
}
dfs(1,0,0);
cout<<0<<endl;
for(int i=1;i<=n;i++) cout<<col[i]<<" ";
return 0;
} 
京公网安备 11010502036488号