Graph Coloring I
https://www.nowcoder.com/acm/contest/203/J
题目描述
修修在黑板上画了一些无向连通图,他发现他可以将这些图的结点用两种颜色染色,满足相邻点不同色。
澜澜不服气,在黑板上画了一个三个点的完全图。修修跟澜澜说,这个图我能找到一个简单奇环。
澜澜又在黑板上画了一个n个点m条边的无向连通图。很可惜这不是一道数数题,修修做不出来了。
澜澜非常得意,作为一位毒瘤出题人,有了好题当然要跟大家分享,于是他把这道题出给你做了。
澜澜不服气,在黑板上画了一个三个点的完全图。修修跟澜澜说,这个图我能找到一个简单奇环。
澜澜又在黑板上画了一个n个点m条边的无向连通图。很可惜这不是一道数数题,修修做不出来了。
澜澜非常得意,作为一位毒瘤出题人,有了好题当然要跟大家分享,于是他把这道题出给你做了。
输入描述:
第一行两个整数n,m (1≤ n,m≤ 3*105
),接下来m行每行两个整数ai
,bi
表示一条边 (1≤ ai
,bi
≤ n)。
保证图连通,并且不存在重边和自环。
输出描述:
如果你能把图二染色,第一行输出0,第二行输出n个整数
表示每个点的颜色 (0≤ xi
≤ 1)。如果有多种合法方案,你可以输出任意一种。
如果你能找到一个简单奇环,第一行输出环长k,第二行输出k个整数
表示环上结点编号 (1≤ yi
≤ n),你需要保证yi
和yi+1
之间有边,y1
和yn
之间有边。如果有多种合法方案,你可以输出任意一种。
如果两种情况都是可行的,你只需要输出任意一种。
如果两种情况都是不可行的,请输出一行一个整数-1。
示例1
输入
3 2 1 2 1 3
输出
0 0 1 1
示例2
输入
3 3 1 2 1 3 2 3
输出
3 1 2 3
用dfs边搜索边染色,看看有没有相邻的节点有相同的颜色,并判断是否有奇环(如果相邻的节点有相同的颜色就说明存在奇环),都不满足的话就输出-1
1 #include<iostream> 2 #include<cmath> 3 #include<vector> 4 #include<cstring> 5 #include<algorithm> 6 #define maxn 300005 7 #define mem(a,b) memset(a,b,sizeof(a)) 8 using namespace std; 9 10 vector<int>ve[maxn]; 11 int book[maxn]; 12 int color[maxn]; 13 int n,m; 14 int flag,Start; 15 16 int dfs(int pos,int fa,int clr,int num){ 17 if(book[pos]){ 18 if(color[pos]==(clr^1)) flag=1; 19 if((num-book[pos])&1){ 20 cout<<num-book[pos]<<endl; 21 Start=pos; 22 return 0; 23 } 24 return 1; 25 } 26 book[pos]=num; 27 color[pos]=clr; 28 for(int i=0;i<ve[pos].size();i++){ 29 if(ve[pos][i]!=fa){ 30 if(!dfs(ve[pos][i],pos,clr^1,num+1)){ 31 if(pos!=Start){ 32 cout<<pos<<" "; 33 return 0; 34 } 35 else{ 36 cout<<pos<<endl; 37 exit(0); 38 } 39 } 40 } 41 } 42 return 1; 43 } 44 45 int main(){ 46 std::ios::sync_with_stdio(false); 47 cin>>n>>m; 48 int a,b; 49 flag=0; 50 for(int i=1;i<=m;i++){ 51 cin>>a>>b; 52 ve[a].push_back(b); 53 ve[b].push_back(a); 54 } 55 mem(book,0); 56 mem(color,-1); 57 if(!dfs(1,0,0,1)) return 0; 58 if(flag){ 59 cout<<-1<<endl; 60 } 61 else if(!flag){ 62 cout<<0<<endl; 63 for(int i=1;i<=n;i++){ 64 if(i!=1){ 65 cout<<" "; 66 } 67 cout<<color[i]; 68 } 69 cout<<endl; 70 } 71 }