サンプル入力
5 4 0 0 1 3 1 4 3 5 4 5 5 4 1 0 1 3 1 4 3 5 4 5 2
サンプル出力
NO YES
問題の意味:個別のNがあり、m個のゲームがあります良いのx、yの悪い人は、以下のMにマッチする必要があり、nは個人が良いか悪いかに分けるかどうかを確認することができます。最後にこの人を知っている必要はありません主にちょうど二部グラフマッチングとして、2つのグループに分けるかどうかを確認するために、良いか悪いかです。そこに競争に参加しなかった1人が知らないで良くない場合は、あること、ありません、が行われている矛盾した場所はNOです。
アイデア:まず、反対色に感染し、接続ポイントを見つけるために良いか悪い人として同定されています。China Unicom社と他のブロックは、過去に横断している、我々は同じ番号が2つの接続点を表示された場合、間違いなく間違っている、1を染めるだろうか分かりません。
コード:
#pragmaコメント(リンカー、 "/ STACK:1024000000,1024000000") の#pragma GCCの最適化(2) の#include <iostreamの> する#include <アルゴリズム> の#include <cstdioを> する#include <CStringの> する#include <キュー> する#include < セット > の#include <cmath> の#include < 文字列 > の#include <マップ> 書式#include <ベクトル> の#include <ctimeの> の#include <スタック> 使用して 名前空間はstdを、 #define MM(B)のmemset(A、B、 ロングLL; CONST 長い 長い MOD = 1E9 + 7 。 const int型 MAXN = 1E4 + 500 ;; const int型 INF = 0x3f3f3f3f 。 const int型 MAX_V = 1005 ; ベクター < INT > G [MAX_V]。 int型V; INTの色[MAX_V]。 ブール DFS(int型 V、INT C) { 色[V] = C。 以下のための(int型 I = 0; I <G [V] .size()。++ I) { 場合(色[G [V] [I]] == C) { 戻り 偽。 } であれば(色[G [V] [I]] == 0 && DFS(G [V] [I]、 - !C)) 戻り 偽。 } を返す 真。 } ボイド)(解く { ため(INT iは= 0 ; I <V; ++ i)が { 場合(色[I] == 1 ) { 場合(DFS(I、!の1 )) { プット(" NO " ); リターン; } } そう であれば(色[I] == - 1 ) { もし - (DFS(I、!1 )) { プット(" NO " )。 リターン; } } } のために(INT iが= 0 ; I <V; ++ i)が { 場合(色[I] == 0 ) { 場合(!DFS(I、1 )) { プット(" NO " )。 リターン; } } } のために(INT iは= 0 ; I <V、I ++ ) { 場合(色[I] == - 5 ) { プット(" NO " )。 リターン; } } プット(" YES " ); } int型のmain() { int型E; INT X、Y。 一方、(〜のscanf(" %D%D%D%D "、&V、&E、およびX&Y)) { int型、A、B 以下のために(INT iが= 0 ; I <V; ++ I) { G [i]が.clear(); 色[I] = - 5 。 } ため(INT iが= 0 ; I <E; ++ I) { scanf関数(" %D%D "、&、&B)。- ; B - ; カラー[A] = 0 ; 色[B] = 0 ; G [A] .push_back(B)。 G [B] .push_back()。 } ため(INT iは= 0 ; I <X; I ++ ) { scanf関数(" %のD "、& )。- ; カラー[A] = 1 。 } のための(INTは iは= 0 ; I <Y; I ++ ) { のscanf(" %dの"、&); - ; 色[A] = - 1 ; } (解決); } 戻り 0 ; }