#include "testlib.h"
#include <vector>
#include <set>
#include <string>
#include <algorithm>

using namespace std;

// 安全的字符串转整数函数，防备用户输出非法字符（如乱码）
int parseStringToInt(const string& arg) {
    int result = 0;
    for (size_t i = 0; i < arg.size(); ++i) {
        if (arg[i] < '0' || arg[i] > '9') {
            quitf(_pe, "Expected integer, but found invalid string: %s", arg.c_str());
        }
        result = result * 10 + (arg[i] - '0');
    }
    return result;
}

// 提取的加边函数，完美兼容 C++98
void add_edge(int u, int v, set<pair<int, int> >& edges, vector<int>& current_deg, int n) {
    if (u < 1 || u > n || v < 1 || v > n) {
        quitf(_wa, "Vertex index out of range: %d or %d", u, v);
    }
    if (u == v) {
        quitf(_wa, "Self-loop detected: %d-%d.", u, v);
    }
    if (u > v) swap(u, v);

    // C++98 必须使用 make_pair
    if (edges.count(make_pair(u, v))) {
        quitf(_wa, "Duplicate edge detected: %d-%d.", u, v);
    }
    edges.insert(make_pair(u, v));

    current_deg[u]++;
    current_deg[v]++;
}

int main(int argc, char* argv[]) {
    registerTestlibCmd(argc, argv);

    int n = inf.readInt();
    vector<int> target_deg(n + 1);
    long long sum_deg = 0;
    for (int i = 1; i <= n; i++) {
        target_deg[i] = inf.readInt();
        sum_deg += target_deg[i];
    }

    // 根据标程输出判断当前图是否有解
    string ans_first = ans.readToken();
    bool possible = (ans_first != "-1");

    // 1. 无解情况的特判
    if (!possible) {
        // 如果正确答案是无解，用户也必须输出 -1
        string ouf_first = ouf.readToken();
        if (ouf_first != "-1") {
            quitf(_wa, "Expected -1 (impossible), but user output %s", ouf_first.c_str());
        }
        quitf(_ok, "Correctly identified as impossible.");
    }

    // 2. 有解情况的处理
    long long expected_edges = sum_deg / 2;
    vector<int> current_deg(n + 1, 0);
    set<pair<int, int> > edges;

    // 仅在期望边数大于 0 时才去读入
    if (expected_edges > 0) {
        // 依然用 readToken 读第一个词，防止有解时用户误输出 -1
        string first_tok = ouf.readToken();
        if (first_tok == "-1") {
            quitf(_wa, "User claimed -1, but a valid graph exists.");
        }

        int u1 = parseStringToInt(first_tok);
        int v1 = ouf.readInt();
        add_edge(u1, v1, edges, current_deg, n);

        // 精准读取剩下的边
        for (long long i = 1; i < expected_edges; i++) {
            int u = ouf.readInt();
            int v = ouf.readInt();
            add_edge(u, v, edges, current_deg, n);
        }
    }

    // 3. 校验是否有多余输出
    // 此时使用 seekEof 是绝对安全的，因为它会自动过滤掉末尾的空格、换行符。
    // 如果过滤完空白符后还有实质性内容，则说明用户输出了多余垃圾数据。
    if (!ouf.seekEof()) {
        if (expected_edges == 0) {
            string wrong_ans = ouf.readToken();
            if (wrong_ans == "-1") quitf(_wa, "User claimed -1, but empty graph (0 edges) is valid.");
        }
        quitf(_wa, "Extra tokens found after reading expected edges.");
    }

    // 4. 最终校验每个节点的度数
    for (int i = 1; i <= n; i++) {
        if (current_deg[i] != target_deg[i]) {
            quitf(_wa, "Vertex %d has degree %d, but expected %d.", i, current_deg[i], target_deg[i]);
        }
    }

    quitf(_ok, "Valid simple graph successfully verified.");
}
