cppAcademy
FROM LEARNING TO COMPETING

Proficient.
Put your skills to the test.

Bulgarian Informatics Group B · 2007–2026

274 independently explained problems: 54 Municipal, 54 Regional, 109 National Olympiad and 57 Autumn Tournament tasks. Difficulty labels are learning estimates, not official ratings. Some events share Junior/IATI or Group A/B problem sets. Special formats, scoring limitations and source clarifications are explained on affected tasks. The two previously featured Autumn problems keep their existing permanent URLs.
GROUP B2021 · EasyAcyclic orientation by a total vertex order

Orient the Monopoly Board without Cycles

Autumn Tournament (2021)

Submission name: monopoly.cpp

Problem summary

Reverse any chosen directed connections so that the resulting graph has no directed cycle. Return one binary decision per edge; minimizing reversals is not required.

Source clarification. The original problem uses a grader interface rather than ordinary stdin/stdout. This page preserves that interface and supplies an explicitly labeled local demonstration driver. The output need not match the sample’s particular valid orientation.

Input

Local demonstration: N M followed by M directed edges. The original judge calls find_reverse(N,M,connections).

Output

An M-character string:1 reverses that edge;0 keeps it. Any acyclic resulting orientation is accepted.

Constraints

3≤N≤500000; 3≤M≤1500000; vertices1..N; no self-loops, duplicate edges or antiparallel edge pairs.

Worked example

Original statement sample.

Input

6 12
1 2
1 5
2 3
2 5
3 4
3 6
4 1
4 5
5 3
5 6
6 1
6 4

Output

000000101011

Solution analysis

  1. Choose a fixed total ordering of the vertices:1,2,…,N. Make every edge point from the smaller endpoint to the larger endpoint. For an original edge u→v, reverse it exactly when u>v.
  2. No graph search or minimum-feedback-edge optimization is needed because the statement accepts any number of reversals. The total order itself supplies a topological ordering.
  3. In the worked input, reverse4→1,5→3,6→1 and6→4. All remaining arrows then increase the vertex number. The displayed string is a different valid answer from the original example’s choice.

Why it works

Along every resulting directed edge, the vertex number strictly increases. A directed cycle would force a strict increase all the way back to its starting number, which is impossible. Hence the returned decisions always produce a DAG.

Complexity: O(M) time and O(M) output space; the rule handles each edge once. The local driver additionally stores the M input pairs.

Watch out. The original submission is a function, not a standalone stdin program. Do not optimize the number of reversed edges unnecessarily. Preserve input-edge order when constructing the string.

Commented C++17 solution

Compile the complete local demonstration with g++ -std=c++17 -DLOCAL. Without LOCAL only the judge function find_reverse is compiled; submit it to the original grader, which supplies main and the input.

#include<iostream>
#include<string>
using namespace std;
string find_reverse(int n,int m,int connections[][2]){
    (void)n;
    string result(m,'0');
    for(int edge=0;edge<m;edge++){
        // All final arrows point from a smaller label to a larger label.
        if(connections[edge][0]>connections[edge][1]){
            result[edge]='1';
        }
    }
    return result;
}
#ifdef LOCAL
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n,m;
    cin>>n>>m;
    int(*connections)[2]=new int[m][2];
    for(int edge=0;edge<m;edge++){
        cin>>connections[edge][0]>>connections[edge][1];
    }
    cout<<find_reverse(n,m,connections)<<'\n';
    delete[]connections;
}
#endif

Source: Arena Olimpiici ↗