#include #include #define MAXN 100000 #define MAXM 1000000 int n, m; int tovarny[MAXN]; // k jakým továrnám patří fáze int nasl[MAXM]; // seznam následníků int zac[MAXN + 1]; // pole začátků v poli následníků int hranyZac[MAXM], hranyKon[MAXM]; // uložení hran (při načítání) int out[MAXN]; // výstupní stupně vrcholů int in[MAXN]; // vstupní stupně vrcholů int in2[MAXN]; // vstupní stupně vrcholů (pro obnovení pole in) int fronty[2][MAXN]; // fronty pro jednotlivé továrny int zacFront[2], konFront[2]; // začátky a konce obou front int poradi[2][MAXN]; // výsledné pořadí pro oba možné začátky int prevozu[2]; // počet převozů // provede topologické třídění s minimalizací počtu továren, // přičemž se začne v továrne prvni void setrid(int prvni) { // vyprázdni fronty for (int i = 0; i < 2; i++) { zacFront[i] = 0; konFront[i] = 0; } // dej do front vrcholy bez vstupních hran for (int i = 0; i < n; i++) { in[i] = in2[i]; // obnov vstupní stupně if (in[i] == 0) { int t = tovarny[i]; fronty[t][konFront[t]] = i; konFront[t]++; } } int akt = prvni; // aktuální továrna int iporadi = 0; while (iporadi < n) { // odebírej z fronty jedné továrny, dokud to jde while (zacFront[akt] < konFront[akt]) { int faze = fronty[akt][zacFront[akt]]; zacFront[akt]++; poradi[prvni][iporadi] = faze; iporadi++; // následníkům fáze zmenši vstupní stupeň for (int i = zac[faze]; i < zac[faze + 1]; i++) { int f = nasl[i]; in[f]--; if (in[f] == 0) { int t = tovarny[f]; fronty[t][konFront[t]] = f; konFront[t]++; } } } // převoz mezi továrnami akt = 1 - akt; prevozu[prvni]++; } prevozu[prvni]--; } int main(void) { scanf("%d%d", &n, &m); // načti továrny int a, b; for (int i = 0; i < n; i++) { scanf("%d", &a); tovarny[i] = a - 1; } // načti hrany for (int i = 0; i < m; i++) { scanf("%d%d", &a, &b); hranyZac[i] = a - 1; hranyKon[i] = b - 1; in2[b - 1]++; out[a - 1]++; } // začátky seznamů následků v poli nasl pro vrcholy zac[0] = 0; for (int i = 1; i < n; i++) { zac[i] = zac[i - 1] + out[i - 1]; } zac[n] = zac[n - 1] + out[n - 1]; // ulož hrany do seznamu následníků for (int i = 0; i < m; i++) { a = hranyZac[i]; // hrany jsou pro každý vrchol ukládány od konce nasl[zac[a] + out[a] - 1] = hranyKon[i]; out[a]--; } // cyklus dle továrny, v níž se začne for (int prvni = 0; prvni < 2; prvni++) { setrid(prvni); } int lepsi = 0; if (prevozu[0] > prevozu[1]) lepsi = 1; // vypiš výsledné pořadí printf("Počet převozů: %d, pořadí:\n", prevozu[lepsi]); for (int i = 0; i < n; i++) { printf("%d ", poradi[lepsi][i] + 1); } printf("\n"); return 0; }