#include <bits/stdc++.h>
using namespace std;

// argv[1] = input file (дървета)
// argv[2] = "correct" output -- не се ползва, задачата е output-only
// argv[3] = отговорът на състезателя (файлът, който се подава в PCMS)
//
// Изход:
//   stdout -> нормализиран резултат в [0,1]  (score/10.0), за да пасва
//             на конвенцията от примерния checker (1.0 = пълен резултат).
//             Ако системата ти очаква целочислени точки 0..10, просто
//             смени реда "cout << score / 10.0" с "cout << score".
//   stderr -> диагностика (X, M, R, score)

static long long readEdgesAndScore(ifstream &inS, ifstream &contS,
                                    long long &totalBad, long long &totalEdges,
                                    string &errMsg) {
    int T;
    if (!(inS >> T)) { errMsg = "Input file е невалиден (липсва брой тестове)"; return -1; }

    for (int tc = 0; tc < T; tc++) {
        int n;
        if (!(inS >> n)) { errMsg = "Input file: липсва n за тест " + to_string(tc + 1); return -1; }

        vector<pair<int,int>> edges(max(0, n - 1));
        for (int i = 0; i < n - 1; i++) {
            int u, v;
            if (!(inS >> u >> v)) {
                errMsg = "Input file: липсва ребро в тест " + to_string(tc + 1);
                return -1;
            }
            edges[i] = {u, v};
        }

        // Четем етикетите на състезателя за този тест случай
        vector<int> label(n + 1, -1);
        vector<char> seen(n + 1, 0);
        bool valid = true;

        for (int i = 1; i <= n; i++) {
            int x;
            if (!(contS >> x)) {
                errMsg = "Отговорът свършва преждевременно (тест " + to_string(tc + 1) + ")";
                return -1; // фатално - няма как да продължим да четем останалите тестове коректно
            }
            if (x < 1 || x > n || seen[x]) {
                valid = false; // невалидна пермутация - "довършваме" четенето, за да не разсинхронизираме потока
            } else {
                seen[x] = 1;
            }
            label[i] = x;
        }

        if (!valid) {
            // Невалиден отговор за този тест: третираме всички негови ребра като лоши
            totalBad += (long long)edges.size();
            totalEdges += (long long)edges.size();
            continue;
        }

        for (auto &e : edges) {
            int u = e.first, v = e.second;
            int lu = label[u], lv = label[v];
            if (__gcd(lu, lv) > 1) totalBad++;
        }
        totalEdges += (long long)edges.size();
    }

    return 0;
}

int main(int argc, char** argv) {
    if (argc < 4) {
        cerr << "Usage: checker <input> <correct_output> <contestant_output>" << endl;
        cout << 0.0 << endl;
        return 0;
    }

    ifstream inS(argv[1]);
    ifstream contS(argv[3]);

    if (!inS.is_open()) {
        cerr << "Не мога да отворя input файла" << endl;
        cout << 0.0 << endl;
        return 0;
    }
    if (!contS.is_open()) {
        cerr << "Не мога да отворя файла на състезателя" << endl;
        cout << 0.0 << endl;
        return 0;
    }

    long long X = 0, M = 0;
    string errMsg;
    long long rc = readEdgesAndScore(inS, contS, X, M, errMsg);

    if (rc < 0) {
        cerr << "Грешка: " << errMsg << endl;
        cout << 0.0 << endl;
        return 0;
    }

    double R = (M == 0) ? 0.0 : (double)X / (double)M;

    int score;
    if (R > 0.4) score = 0;
    else if (R > 0.33) score = 1;
    else if (R > 0.26) score = 2;
    else if (R > 0.19) score = 3;
    else if (R > 0.12) score = 4;
    else if (R > 0.05) score = 5;
    else if (R > 0.01) score = 6;
    else if (R > 0.005) score = 7;
    else if (R > 0.001) score = 8;
    else if (R > 0.0) score = 9;
    else score = 10; // R == 0

    cerr << "X (лоши ребра) = " << X
         << ", M (общо ребра) = " << M
         << ", R = " << R
         << ", точки = " << score << " / 10" << endl;

    cout << fixed << setprecision(6) << (score / 10.0) << endl;
    return 0;
}
