Problem p01897 - Generation 1

Orig Description

G: DAG Trio / DAG Trio
This problem is the same setting as D: DAG Trio (Easy) except for the constraints.
Prologue
My little brother has been muttering "dag torio" recently.
Worried, I looked it up and found that in his class, $k$-DAG (a directed graph in which removing $k$ edges makes the number of connected components $k$, and all of them are DAG) is popular, and 3-DAG is called DAG trio.
To be respected by my brother, I decided to make a program that determines whether a given graph is DAG trio or not.
Problem Statement
Given a directed graph with $N$ vertices and $M$ edges.
Each vertex is numbered from $1$ to $N$.
Each directed edge is numbered from $1$ to $M$.
Directed edge $i$ goes from vertex $a_i$ to vertex $b_i$.
The graph is connected and simple (there is a path between any two vertices when ignoring the direction of edges, and there are no self-loops or multiple edges).
If the given graph is DAG trio, output "YES", otherwise output "NO".
Input
$N \ M$
$a_1 \ b_1$
$a_2 \ b_2$
$\vdots$
$a_M \ b_M$
Constraints
$3 \le N \le 500$
$\max(3, N−1) \le M \le 30000$
$1 \le a_i, b_i \le N$
The graph is connected when ignoring the direction of edges.
$a_i \neq b_i$ for all $i$.
$\{a_i, b_i\} \neq \{a_j, b_j\}$ for all $i \neq j$.
Output
Output "YES" or "NO" in a single line.
Sample
Sample Input 1
3 3
1 2
2 3
3 1
Sample Output 1
YES
Sample Input 2
6 7
1 2
2 3
4 3
4 5
5 6
6 4
3 6
Sample Output 2
YES
Sample Input 3
7 10
4 2
4 7
4 6
2 7
2 5
2 1
5 6
1 3
6 3
4 3
Sample Output 3
NO
Sample Input 4
4 4
1 2
3 2
4 3
2 4
Sample Output 4
YES
Sample Input 5
8 9
5 1
3 8
1 2
4 8
4 7
7 5
6 5
3 2
4 2
Sample Output 5
YES

Extracted Specification

An integer N (3 ≤ N ≤ 500), representing some quantity or size.
An integer M (max(3, N−1) ≤ M ≤ 30000), representing some quantity or size.
A list of M pairs of integers, where each integer in the pair is between 1 and N.

### Example Input:

```
3 3
1 2
2 3
3 1
```

### Function Signature:
Write a function f(N, M, edges) that takes in the input.
def f(N: int, M: int, edges: List[Tuple[int, int]]): 
    ''' 
    N: an integer 
    M: an integer 
    edges: a list of tuples, each containing two integers
    '''

Test Case Generator

Sure! Here is a Python function to generate test cases for the "DAG Trio" problem:

```python
import random

def generate_dag_trio_test_case():
    N = random.randint(3, 500)
    M = random.randint(max(3, N-1), 30000)
    
    edges = set()
    while len(edges) < M:
        a = random.randint(1, N)
        b = random.randint(1, N)
        if a != b and (a, b) not in edges and (b, a) not in edges:
            edges.add((a, b))
    
    edges = list(edges)
    random.shuffle(edges)
    
    test_case = f"{N} {M}\n"
    for a, b in edges:
        test_case += f"{a} {b}\n"
    
    return test_case.strip()

# Example usage:
print(generate_dag_trio_test_case())
```

### Explanation:

1. **Vertices and Edges Count:**
    - `N` is chosen randomly between 3 and 500.
    - `M` is chosen randomly between the maximum of 3 and \(N-1\) to 30000.

2. **Edges Generation:**
    - A set `edges` is used to store unique edges.
    - Random edges `(a, b)` are generated ensuring:
        - `a` is not equal to `b` (no self-loops).
        - Each edge `(a, b)` is unique and not already in the set (no multiple edges).
        - Ensuring the graph is simple and connected (in practice, this random method combined with the constraints helps generate a connected graph).

3. **Output Format:**
    - The test case is returned as a formatted string where:
        - The first line is `N M`.
        - Each subsequent line represents an edge `a b`.

This generator will help create randomized test cases suitable for the "DAG Trio" problem while respecting the constraints provided.

Extract Arguments

def extract_arguments(fh):
    N, M = map(int, fh.readline().strip().split())
    edges = [tuple(map(int, fh.readline().strip().split())) for _ in range(M)]
    return N, M, edges

# if __name__ == "__main__":
#     input_path = sys.argv[1]
#     with open(input_path, 'r') as fh: 
#     N, M, edges = extract_arguments(fh)
#     f(N, M, edges)