問題描述:對於給定的圖G,如果存在一種用兩種顏色對頂點着色的方案,使得圖中任意一條邊所連接的兩個頂點着不同顏色,則稱圖G是可二着色的。
實驗任務:對於給定的圖G,計算G是否可二着色
數據輸入:第1行有2個正整數m, n,表示給定圖G有n個頂點和m條邊,頂點編號1,2,...,n。接下來m行中,每行有兩個正整數u,v,表示圖G的一條邊(u,v)
結果輸出:可二着色輸出"Yes",否則輸出"No"
直觀想法,深搜或者廣搜,一個頂點塗一個顏色,下一個頂點塗相反顏色。如果搜索到塗過的頂點,判斷與當前頂點顏色是否相同,是則表明無法二着色,立即退出。直至全部搜索完成。
事實上,圖如果無法二着色,那麼必然有環,且環的頂點數必然爲奇數,但是這個有什麼算法呢,emmm,沒想到,直接用最簡單直觀的深搜吧
#include <bits/stdc++.h>
using namespace std;
typedef struct{
int vexnum; //頂點數
int arcnum; //邊數
int **arc; //鄰接矩陣
}Matrix_Graph;
Matrix_Graph CreateNewGraph(int n, int m)
{
int i, j;
Matrix_Graph graph;
graph.vexnum = n;
graph.arcnum = m;
graph.arc = new int*[n+1];
for(i = 1; i <= n; ++i){
graph.arc[i] = new int[n+1];
for(j = 1; j <= n; ++j)
graph.arc[i][j] = 0;
}
while( m-- ){
cin >> i >> j;
graph.arc[i][j] = graph.arc[j][i] = 1;
}
return graph;
}
void dfs(const Matrix_Graph& graph, int vex, bool visited[], bool color[], bool nowColor, bool& res)
{
visited[vex] = true; // 標記訪問
color[vex] = nowColor; // 塗色
cout << "vex " << vex << ": ";
if( color[vex] ){
cout << "red\n";
}else{
cout << "black\n";
}
for(int i = 1; i <= graph.vexnum; ++i)
{
// 首先判斷兩點是否連通
if( graph.arc[vex][i] == 1 )
{
// 若訪問過,且顏色一致,說明失敗
if( visited[i] && color[i]==nowColor ){
res = false;
return;
}else if( !visited[i] ){
// !nowColor表示下一個頂點塗另一種顏色
dfs(graph, i, visited, color, !nowColor, res);
if( !res )
return;
}
}
}
}
void Dfs_Graph(const Matrix_Graph& graph, bool& res)
{
bool visited[graph.vexnum+1] = {false};
bool color[graph.vexnum+1] = {false};
bool nowColor = false;
for(int i = 1; res && i<=graph.vexnum; ++i)
if( !visited[i] )
dfs(graph, i, visited, color, nowColor, res);
}
bool Cover_2color(const Matrix_Graph& graph)
{
bool res = true;
Dfs_Graph(graph, res);
return res;
}
int main()
{
int n, m;
cin >> n >> m;
Matrix_Graph graph = CreateNewGraph(n, m);
if( Cover_2color(graph) ){
cout << "Yes\n";
}else{
cout << "No\n";
}
return 0;
}
//Test1
//12 10
//1 3
//1 6
//2 8
//3 7
//4 5
//5 6
//5 8
//2 9
//9 10
//11 12
//Test2
//12 10
//1 3
//1 6
//2 8
//3 7
//4 5
//5 6
//5 8
//2 9
//9 10
//8 9