3126 – Arbori in graf

De la Universitas MediaWiki
Versiunea pentru tipărire nu mai este suportată și poate avea erori de randare. Vă rugăm să vă actualizați bookmarkurile browserului și să folosiți funcția implicită de tipărire a browserului.

Cerința

În judeţul lui Dorel sunt n localităţi legate între ele prin m drumuri. Dorel e interesat să afle în câte moduri se pot alege n-1 drumuri din cele m date, astfel încât folosind aceste drumuri să se poată ajunge de la orice localitate la oricare alta.

Date de intrare

Fișierul de intrare arbori_in_grafIN.txt conține pe prima linie numerele n şi m, iar pe următoarele m linii câte o pereche de numere distincte de la 1 la n, reprezentând două localităţi între care există drum.

Date de ieșire

Fișierul de ieșire arbori_in_grafOUT.txt va conține pe prima linie numărul de moduri cerut, modulo 1.000.000.007.

Restricții și precizări

  • 2 ≤ n ≤ 50
  • 0 ≤ m ≤ n(n-1)/2

Exemplul 1

arbori_in_grafIN.txt:

2 1

1 2

arbori_in_grafOUT.txt:

1

Exemplul 2

arbori_in_grafIN.txt:

99999999999 1

1 2

Output:

Invalid input! Please check the conditions: 2 ≤ n ≤ 50 and 0 ≤ m ≤ n(n-1)/2

Rezolvare

MOD = 1000000007

def gcd(x, y, a, b):
    if b == 0:
        x, y = 1, 0
    else:
        gcd(x, y, b, a % b)
        aux = x
        x = y
        y = aux - y * (a // b)

def inverse(x):
    ins, inv = 0, 0
    gcd(inv, ins, x, MOD)
    if inv <= 0:
        inv = MOD + inv % MOD
    return inv

def determinant(a, n):
    semn = 1

    for i in range(1, n):
        if a[i][i] == 0:
            for j in range(i + 1, n + 1):
                if a[j][i] != 0:
                    a[i], a[j] = a[j], a[i]
                    semn *= -1
                    break

            if not a[i][i]:
                return 0

        for j in range(i + 1, n + 1):
            if a[i][i] < 0:
                a[i][i] += MOD
            p = (-a[j][i] * inverse(a[i][i])) % MOD
            if p < 0:
                p += MOD
            for k in range(i, n + 1):
                a[j][k] = (a[j][k] + p * a[i][k]) % MOD
                if a[j][k] < 0:
                    a[j][k] += MOD

    pp = 1
    for i in range(1, n + 1):
        pp = (pp % MOD * a[i][i] % MOD) % MOD
    return pp * semn

def validate_input(n, m):
    return 2 <= n <= 50 and 0 <= m <= n * (n - 1) // 2

def main():
    with open("arbori_in_grafIN.txt", "r") as f:
        n, m = map(int, f.readline().split())

        if not validate_input(n, m):
            print("Invalid input! Please check the conditions: 2 ≤ n ≤ 50 and 0 ≤ m ≤ n(n-1)/2")
            return

        a = [[0] * 51 for _ in range(51)]
        for _ in range(m):
            x, y = map(int, f.readline().split())
            a[x][y] = -1
            a[y][x] = -1
            a[x][x] += 1
            a[y][y] += 1

    det = determinant(a, n - 1)

    with open("arbori_in_grafOUT.txt", "w") as g:
        g.write(str(det))

if __name__ == "__main__":
    main()