알고리즘 공부

백준 이분 그래프

컴퓨터과학 2023. 9. 23. 21:33

https://www.acmicpc.net/problem/1707

 

1707번: 이분 그래프

입력은 여러 개의 테스트 케이스로 구성되어 있는데, 첫째 줄에 테스트 케이스의 개수 K가 주어진다. 각 테스트 케이스의 첫째 줄에는 그래프의 정점의 개수 V와 간선의 개수 E가 빈 칸을 사이에

www.acmicpc.net

dfs문제인데 한 3일 넘게 걸려서 오늘 스프링 공부를 못햇네요 ㅠ 

일단 중요한 키포인트는  아래 코드인데 

if (colors[glists[k][i] - 1]==0) {
		  if (dfs(glists[k][i], 3 - cnt) == false) {
				return false;
		  }
}else if(colors[glists[k][i] - 1]==cnt){
			return false;
}

colors가 0이면 아직 색이 없는 상태

colors가 1이면 1번칼라 

colors가 2이면 2번 칼라로 지정 됩니다.

여기서 현재 칼라가 잇는 상태에서 색칠할 칼라가 동일한 경우 그래프는 이분 그래프가 될수가 없습니다.

colors[glists[k][i] - 1]==cnt

즉 예를들어 아래와 같은 노드가 연결이 되있다고 가정하겠습니다.

1 2
3 4
3 5
4 5

그리고 colors의 번호가 들어가는 값인 1을 R, 2를 B 칼라라고 가정하겠습니다.

인접노드로 만들면 아래와 같은 리스트가 만들어집니다.

1 - 2
2 - 1
3 - 4 - 5
4 - 3- 5
5 - 3 -4

시작은 1번노드에서 1은 R칼라가 됩니다. colors[0]=1; cnt=1

그리고 다음 노드가 2번으로 이동시 2번은 B 칼라가 됩니다. colors[1]=2; cnt=2 

그다음 2번 노드로 이동시 끊어진 노드이기에 

 

2번노드로 다시 시작합니다. colors[1]은 1이기 때문에 if (colors[i-1] == 0) 아니기 때문에 dfs에서 패스가 됩니다.

 

그러면 다음인 3번노드로 시작합니다. 

 3은 B 칼라가 됩니다. 칼라는 colors[2]=1;가 됩니다.cnt=1

다음은 4번 노드로 가서 칼라는 colors[3]=2이 됩니다. cnt=2 

다음은 3번 노드로 다시 가기 때문에  colors[2]=1이고  cnt는 1이므로 서로 다르므로 true로 return합니다.

그래서 return하고 조건인 false가 아니기 때문에 다시 return합니다. 돌아기 때문에 5번 노드로 갑니다.

 

그러면 맨처음 3은 칼라 B 상태에서 5번을 노드로 갑니다. 5번 노드는 colors[4]=2가 됩니다. cnt=2;

5번 노드의 3번과 4번을 체크합니다. 그러면 이때 colors[3]번이 cnt=2와 동일하기 때문에 return false가 되어 

이분그래프가 아니게 됩니다.  

 

정답:

#include <iostream>
#include <vector>
#include <queue>
#include<string>
#include<algorithm>
#include<cmath>
#include<unordered_map>
#include<map>
#include<stack>
using namespace std;

struct Point {
	int i, j;
	int cnt = 0;
	
};

void Prints(vector<vector<int>>maps, int n, int m) {
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			cout << maps[i][j] << " ";
		}
		cout << endl;
	}
	cout << endl;
}

void Prints(vector<vector<bool>>maps, int n, int m) {
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			cout << maps[i][j] << " ";
		}
		cout << endl;
	}
	cout << endl;
}
void Prints(vector<vector<char>>maps, int n, int m) {
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			cout << maps[i][j];
		}
		cout << endl;
	}
	cout << endl;
}
void Prints(vector<vector<vector<char>>>maps, int n, int m, int k) {
	for (int t = 0; t < k; t++) {
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				cout << maps[t][i][j];
			}
			cout << endl;
		}
		cout << endl;
	}
	cout << endl;
}

void Prints(vector<vector<vector<bool>>>maps, int n, int m, int k) {
	for (int t = 0; t < k; t++) {
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				cout << maps[t][i][j];
			}
			cout << endl;
		}
		cout << endl;
	}
	cout << endl;
}
void Prints(vector<int>line, int n) {
	for (int i = 0; i < n; i++) {
		cout << line[i] << ",";
	}
	cout << endl;
}
void Prints(string str, int n) {
	for (int i = 0; i < n; i++) {
		cout << str[i] << ",";
	}
	cout << endl;
}

bool checkmaps(vector<vector<int>>maps, vector<vector<int>>anw, int n, int m) {
	bool bCheck = false;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			if (maps[i][j] != anw[i][j]) {
				bCheck = true;
				i = n + 1;
				j = m + 1;
				continue;
			}
		}

	}
	return bCheck;

}
bool findstart(vector<vector<int>>maps, vector<vector<int>>anw, int n, int m, int) {
	bool bCheck = false;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			if (maps[i][j] != anw[i][j]) {
				bCheck = true;
				i = n + 1;
				j = m + 1;
				continue;
			}
		}

	}
	return bCheck;

}
bool checkmaps(vector<vector<bool>>maps, int n, int m) {
	//bool bCheck = false;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			if (maps[i][j] == false) {
				//bCheck = true;
				return true;
			}
		}
	}
	return false;
}
struct Data {
	Point p;
	int cnt;
	int sum;
};
vector<vector<int>>glists;
vector<bool>gbChecks;
vector<int>colors;
int gv, ge;
bool bConfirm = false;
bool dfs( int k ,int cnt) {

	gbChecks[k - 1] = true;
	colors[k - 1] = cnt;
	for (int i = 0; i < glists[k].size(); i++) {
		if (colors[glists[k][i] - 1]==0) {
		  if (dfs(glists[k][i], 3 - cnt) == false) {
				return false;
		  }
		}
		else if(colors[glists[k][i] - 1]==cnt){
			return false;
		}
	}
	return true; 
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);
	//그래프
	//정점 집합을 둘로 분열
	//각 집합에 속한 정점끼리는 인접하지 않도록 분할 할수 잇을때
	//그러한 그래프를 특별히 이분 그래프 라고 한다.
	int k;
	cin >> k;
	
	//각 정점은 1부터 v까지 차례로 번호가 붙어 잇다.
	//e개의 줄에 걸쳐 간선에 대한 정보가 주어지는데 
	vector<string>anw;
	for (int t = 0; t < k; t++)
	{
		bConfirm = false;
		//v 정점,e간선의 갯수
		int v, e;
		cin >> v >> e;
		gv = v;
		ge = e;
		vector<vector<int>>lists(v+1);
		vector<bool>bChecks(v,false);
		gbChecks=bChecks;
		colors.clear();
		for (int i = 0; i < v; i++) {
			colors.push_back(0);
		}

		for (int i = 0; i < e; i++) {
			int x, y;
			cin >> x >> y;
			
			if (x > y) {
				int tmp = x;
				x = y;
				y = tmp;
			}

			lists[x].push_back(y);
			lists[y].push_back(x);

		}
		glists = lists;
		for (int i = 1; i < v + 1; i++) {
			if (colors[i-1] == 0) {
				bool bTEST = dfs(i, 1);
				if (bTEST == false) {
					bConfirm = true;
					break;
				}
			}
		}

		if (bConfirm == true) {
			anw.push_back("NO");
		}
		else {
			anw.push_back("YES");
		}
	}
	for (int i = 0; i < anw.size(); i++)
	{
		cout << anw[i] << endl;
	}
}