제출 #1276498

#제출 시각아이디문제언어결과실행 시간메모리
1276498cpismylifeOwOViruses (BOI20_viruses)C++20
100 / 100
332 ms27380 KiB
#include <bits/stdc++.h>

using namespace std;

const long long mod = 1e9 + 7;
const int MaxN = 1e2 + 5;

int g, n, m;
vector<int> nxt[MaxN];
vector<int> trans[MaxN];

void Inp()
{
    cin >> g >> n >> m;
    for (int x = 1; x <= n; x++)
    {
        int u, k;
        cin >> u >> k;
        trans[u].push_back(x);
        for (int y = 1; y <= k; y++)
        {
            int p;
            cin >> p;
            nxt[x].push_back(p);
        }
    }
}

struct Node
{
    int child[2];
    int nxt[2];
    int par, cnt, suflink, exist, prech;

    Node() = default;

    Node(int p, int ch)
    {
        par = p;
        prech = ch;
        exist = 0;
        cnt = child[0] = child[1] = nxt[0] = nxt[1] = suflink = -1;
    }
};

int curPos;
Node Trie[MaxN * MaxN];

int GetNxt(int u, int k);

int SufLink(int u)
{
    if (Trie[u].suflink == -1)
    {
        if (u == 0 || Trie[u].par == 0)
        {
            Trie[u].suflink = 0;
        }
        else
        {
            Trie[u].suflink = GetNxt(SufLink(Trie[u].par), Trie[u].prech);
        }

    }
    return Trie[u].suflink;
}

int GetNxt(int u, int k)
{
    if (Trie[u].nxt[k] == -1)
    {
        if (Trie[u].child[k] == -1)
        {
            if (u == 0)
            {
                Trie[u].nxt[k] = 0;
            }
            else
            {
                Trie[u].nxt[k] = GetNxt(SufLink(u), k);
            }
        }
        else
        {
            Trie[u].nxt[k] = Trie[u].child[k];
        }
    }
    return Trie[u].nxt[k];
}

int Count(int u)
{
    if (u == 0)
    {
        Trie[u].cnt = 0;
        return 0;
    }
    if (Trie[u].cnt != -1)
    {
        return Trie[u].cnt;
    }
    Trie[u].cnt = Count(Trie[u].suflink) + Trie[u].exist;
    return Trie[u].cnt;
}

struct PQNode
{
    int u, st, ed;
    long long w;

    PQNode(int _u, int _st, int _ed, long long _w)
    {
        u = _u;
        st = _st;
        ed = _ed;
        w = _w;
    }

    bool operator < (const PQNode& other) const
    {
        return this->w > other.w;
    }
};

vector<pair<int, int>> graph[2 * MaxN];
vector<pair<int, int>> revgraph[2 * MaxN];
long long F[2 * MaxN][MaxN][MaxN];
bool visited[2 * MaxN][MaxN][MaxN];
priority_queue<PQNode> pq;

void Exc()
{
    curPos = 0;
    Trie[curPos] = Node(-1, -1);
    for (int w = 1; w <= m; w++)
    {
        int k, pos = 0;
        cin >> k;
        for (int x = 1; x <= k; x++)
        {
            int p;
            cin >> p;
            if (Trie[pos].child[p] == -1)
            {
                curPos++;
                Trie[curPos] = Node(pos, p);
                Trie[pos].child[p] = curPos;
            }
            pos = Trie[pos].child[p];
        }
        Trie[pos].exist++;
    }
    for (int x = 0; x <= curPos; x++)
    {
        SufLink(x);
        GetNxt(x, 0);
        GetNxt(x, 1);
    }
    for (int x = 0; x <= curPos; x++)
    {
        Count(x);
    }
    int curn = g - 1;
    for (int u = 0; u < g; u++)
    {
        for (int x : trans[u])
        {
            if ((int)nxt[x].size() == 1)
            {
                graph[nxt[x][0]].push_back(make_pair(u, -1));
            }
            else
            {
                int pre = nxt[x][0];
                for (int y = 1; y < (int)nxt[x].size() - 1; y++)
                {
                    curn++;
                    graph[pre].push_back(make_pair(curn, nxt[x][y]));
                    revgraph[nxt[x][y]].push_back(make_pair(curn, pre));
                    pre = curn;
                }
                graph[pre].push_back(make_pair(u, nxt[x].back()));
                revgraph[nxt[x].back()].push_back(make_pair(u, pre));
            }
        }
    }
    for (int x = 0; x <= curPos; x++)
    {
        if (Trie[x].cnt == 0 && Trie[Trie[x].nxt[0]].cnt == 0)
        {
            pq.push(PQNode(0, x, Trie[x].nxt[0], 1));
        }
        if (Trie[x].cnt == 0 && Trie[Trie[x].nxt[1]].cnt == 0)
        {
            pq.push(PQNode(1, x, Trie[x].nxt[1], 1));
        }
    }
    while (!pq.empty())
    {
        PQNode p = pq.top();
        pq.pop();
        if (visited[p.u][p.st][p.ed])
        {
            continue;
        }
        //cout << p.u << " " << p.st << " " << p.ed << " " << p.w << "\n";
        F[p.u][p.st][p.ed] = p.w;
        visited[p.u][p.st][p.ed] = true;
        for (pair<int, int> x : graph[p.u])
        {
            int v = x.first, w = x.second;
            if (w == -1)
            {
                if (!visited[v][p.st][p.ed])
                {
                    pq.push(PQNode(v, p.st, p.ed, p.w));
                }
            }
            else
            {
                for (int y = 0; y <= curPos; y++)
                {
                    if (Trie[y].cnt == 0 && !visited[v][p.st][y] && visited[w][p.ed][y])
                    {
                        pq.push(PQNode(v, p.st, y, p.w + F[w][p.ed][y]));
                    }
                }
            }
        }
        for (pair<int, int> x : revgraph[p.u])
        {
            int v = x.first, w = x.second;
            for (int y = 0; y <= curPos; y++)
            {
                if (Trie[p.st].cnt == 0 && !visited[v][y][p.ed] && visited[w][y][p.st])
                {
                    pq.push(PQNode(v, y, p.ed, p.w + F[w][y][p.st]));
                }
            }
        }
    }
    for (int x = 2; x < g; x++)
    {
        long long res = -1;
        for (int y = 0; y <= curPos; y++)
        {
            if (visited[x][0][y])
            {
                if (res == -1)
                {
                    res = F[x][0][y];
                }
                res = min(res, F[x][0][y]);
            }
        }
        if (res == -1)
        {
            cout << "YES\n";
        }
        else
        {
            cout << "NO " << res << "\n";
        }
    }
}

int main()
{
    //freopen("VIRUSES.INP", "r", stdin);
    //freopen("VIRUSES.OUT", "w", stdout);
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    int test = 1;
    //cin >> test;
    for (int x = 1; x <= test; x++)
    {
        Inp();
        Exc();
    }
    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...