문제의 의미
https://vjudge.net/problem/CodeForces-1217D
반지의 그 어느 것도 하나의 색상입니다, 그래서 당신은 사용되는 색상의 수를 최소화해야하는 방향 그래프 색상을주십시오.
사고
그것은 유향 그래프이기 때문에, 각 링 두 가지 색상이 만날 수 있습니다. 따라서, (2)의 최대, 최소 1.
1 DFS를 법 :
방향성 비순환 그래프 분석 DFS를 사용하여, 컬러 엣지 2의 마지막 조각을 구성하는 각 링은, (A)는 남은 염색.
2 위상 정렬 방법
점의 수는 다음 링 단조하지, 마지막 포인트는 시작 지점으로 다시 연결됩니다 때문에 경우 쉽게, 유향 그래프, 찾을 수 있습니다.
우리가 유를 넣어 그래서, 다음 출력 염색 프로토콜이있는 경우 V는, 링, 2를 염색 한 후 위상 정렬이 선고 링 그렇지 않으면 최대 출력 1 <V는 1, u는 염색>.
코드
방법 1 :
#INCLUDE <비트 / stdc ++ H.> 네임 스페이스를 사용하여 표준; #DEFINE INF 0x3f3f3f3f #DEFINE LL 긴 긴 CONST INT N = 5e3 + (5); CONST INT 개조 1E9 + = 7; CONST 두 EPS = 1E-8; CONST 이중 PI = ACOS (-1.0); #DEFINE lowbit (X) (X는 (- X)) 벡터 <INT> g [N]; [N]과 E INT [N] [N], 힘 [N], COL [N], GG; 보이드 DFS (INT U) { INT SZ = g [U] 크기는 (); 에서 [U]는 1 =; 대해 INT (I = 0; I <SZ; I ++) { INT V = g [U] [I]; 경우 (힘이 [V]!) { 힘이 [V] = 1; COL [E [U] [V] = 1; DFS (V); } 다른 ([V]에 있으면) { COL [E [U] [V] = 2; GG = 1; } 다른 { COL [E [U] [V] = 1; } } 의 [U] = 0; } INT 주 () { 표준 : IOS :: sync_with_stdio (거짓); INT의 N, m; 반면 (CIN >> >> N m) { memset 함수 (힘, 0는 sizeof (힘)); 위한 (INT 난 = 1; I <= m; I ++) { INT U, V; CIN >> >> U V; g [U] .push_back (V); E [U]는 [V] 나 =; } GG = 0; 위한 (INT 난 = 1; I <= N; I ++) { (! 힘 [I])의 경우 { // COL [I] = 1; 힘 [I] = 1; DFS (I); } } (GG!의) 경우에 { COUT << 1 << ENDL; 위한 (INT 난 = 1; I <= m; I ++) COUT << 1 << ""; COUT << ENDL; } 다른 { COUT << 2 << ENDL; 경우 (; I <= m I ++ INT 난 = 1) COUT << COL [I]를 << ""; COUT << ENDL; } } 0을 리턴; }
방법 2 :
#INCLUDE <비트 / stdc ++ H.> 네임 스페이스를 사용하여 표준; #DEFINE INF 0x3f3f3f3f #DEFINE LL 긴 긴 CONST INT N = 200,005; CONST INT 개조 1E9 + = 7; CONST 두 EPS = 1E-8; CONST 이중 PI = ACOS (-1.0); #DEFINE lowbit (X) (X는 (- X)) 벡터 <INT> g [N]; INT COL [N], 뒤 [N]; INT의 N, m; 부울 TOPO () { 큐 <INT> Q; 위한 (INT 난 = 1; I <= N; I ++) 경우 (뒤 [I] == 0) q.push (I); INT CNT = 0; 반면 (q.empty (!)) { INT t = q.front (); 대 (INT I : G [t]) { 뒤 [I] -; 경우 (뒤 [I] == 0) q.push (I); } CNT ++; () q.pop; } 경우 (CNT = N!) 복귀 거짓; true를 반환; } INT 주 () { 표준 : IOS :: sync_with_stdio (거짓); CIN >> >> N m; 위한 (INT 난 = 1; I <= m; I ++) { INT U, V; CIN >> >> U V; g [U] .push_back (V); COL [I] = (U <V); 뒤 [V] ++; } (TOPO ()) 경우에 { COUT << 1 << ENDL; 위한 (INT 난 = 1; I <= m; I ++) COUT << 1 << ""; COUT << ENDL; COUT << 2 << ENDL; 경우 (; I <= m I ++ INT 난 1 =) COUT을 << COL [I] +1 << ""; COUT << ENDL; } 0을 반환; }