D.グルメ選択
トピックへのリンク:https://codeforces.com/problemset/problem/1131/D
トピックの効果:NULL
問題解決のアイデア:等以上のような2つの料理の間に等号、そして、その数は同じでなければなりませんので、我々は動作点を削減する必要があります
それらの間の関係があるので、それは、ばらばらのセットを使用して、皿の間の順序を決定することであるしなければならない、我々は、使用する必要性に、この時間を2点間の建設側を考慮することができます
トポロジカルソートすることができます
#include <ビット/ STDC ++ H> 使用して 名前空間STDを、 typedefの長い 長いLL。 const int型 MAXN = 1E4 + 10 。 int型前[MAXN]、中に [MAXN]、アウト[MAXN]、VIS [MAXN]、[MAXN] ANS; ベクター < INT > G [MAXN]。 INT(見つけるint型I) { 場合(I ==事前[i])とリターン[i]を事前。 他の リターン検索(前[I]); } ボイド組合(int型のx、int型のY) { int型XX = 検索(X) INT YY = (y)を見つけます。 場合(!XX = yyは)[XX] =事前YYを。 } int型のmain() { int型、N M。 CIN >> N >> M。 以下のために(int型 i = 1 ; iが<= N + M Iは、++は) { 事前[I] = I。 } チャー S [ 1100 ] [ 1100 ]。 以下のために(int型 i = 1 ; iが<= N; iは++ ) { scanf関数(" %sの" S、[I] +1 ); 用(INT J = 1 J ++; J <= M ) { もし、(S [I] [J] == ' = ')組合(I、J + N)。 / * 他の場合(S [I] [J] == '>')G [検索(J + N)]一back(見つける(I))、++ [(I)を見つける]に。 。他G [(I)検索]一back((j + n)を見つける。)、++ [(j + n)を検索]で、* / } } のための(int型 i = 1 ; iが<= N; iが++ ){ ため(INT J = 1 ; J <= Mであり、j ++ ) 場合(S [i]は[J] == ' >' ){ G [検索(J + N)])一back((I見つけます。)。で [検索(I)] ++ ; } そう であれば(S [I] [J] == ' < ')G [(I)検索]一back((j + n)を見つける。)、で ++ [(J + n)を見つけます] 。 } スタック < INT > Q。 以下のために(int型 i = 1 ; iが<= N + M iは++ ) { 場合(で [検索(I)] == 0 ) { // COUT <<見つける(I)<< ENDLと、 q.push(見つける(I)); VIS [(I)検索] = 1; ANS [(I)検索] = 1 。 } } ながら(!q.empty()) { int型、U = q.top()。 q.pop(); 以下のために(int型 i = 0 ; I <G [U] .size(); iは++ ) { int型、V = G [U] [I]。 で [検索(V)] - 。 もし(で [検索(V)] == 0 &&!VIS [検索(V)]) { VIS [検索(V)] = 1 。 ANSは、[検索(V)]= ANSは、[検索(U)] + 1 。 q.push(見つける(V)); } } } のために(int型 i = 1 ; iが<= N + Mは、iは++ ) { 場合(!VIS [(I)見つけること]) { COUT << " NO \ nを" 。 リターン 0 ; } } COUT << " YES " << ENDL。 以下のために(int型 i = 1 ; iが++; iが<= N ) { もし(!I = 1)COUT << " " ; COUT << ANS [検索(I)]。 } COUT << ENDL。 以下のために(int型 I = 1 ; I <= M iは++ ) { 場合(!I = 1)COUT << " "を、 COUT << ANS [見つける(iは+ n)を]。 } 戻り 0 。 }