Submission #1345377

#TimeUsernameProblemLanguageResultExecution timeMemory
1345377alexddBoard Game (JOI24_boardgame)C++20
68 / 100
4093 ms10316 KiB
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int INF = 1e18;
int n,m,k;
vector<int> con[50005];
bool iss[50005];
int init[50005];
int rez[50005];

int dist1[50005];
void calc_closest1()
{
    deque<int> dq;
    for(int i=1;i<=n;i++)
    {
        if(iss[i])
        {
            dist1[i] = 0;
            dq.push_back(i);
        }
        else
        {
            dist1[i] = INF;
        }
    }
    while(!dq.empty())
    {
        int nod = dq.front();
        dq.pop_front();

        for(int adj:con[nod])
        {
            if(dist1[adj] > dist1[nod] + 1)
            {
                dist1[adj] = dist1[nod] + 1;
                dq.push_back(adj);
            }
        }
    }
}

int best11[50005];
void calc_11()
{
    deque<int> dq;
    for(int i=1;i<=n;i++)
    {
        best11[i] = INF;
        if(!iss[i])
            continue;
        bool bun = 0;
        for(int adj:con[i])
            if(iss[adj])
                bun = 1;
        if(bun)
        {
            best11[i] = -1;
            dq.push_back(i);
        }
    }
    while(!dq.empty())
    {
        int nod = dq.front();
        dq.pop_front();
        for(int adj:con[nod])
        {
            if(iss[adj])
            {
                if(best11[adj] > best11[nod])
                {
                    best11[adj] = best11[nod];
                    dq.push_front(adj);
                }
            }
            else
            {
                if(best11[adj] > best11[nod] + 1)
                {
                    best11[adj] = best11[nod] + 1;
                    dq.push_back(adj);
                }
            }
        }
    }
    for(int i=1;i<=n;i++)
        if(iss[i] && best11[i] < INF)
            best11[i]++;
}

int direct[50005];
void calc_directly()//see if we can reach some nodes without going through stop nodes
{
    deque<int> dq;
    for(int i=1;i<=n;i++)
        direct[i] = INF;
    direct[init[1]] = 0;
    dq.push_back(init[1]);
    while(!dq.empty())
    {
        int nod = dq.front();
        dq.pop_front();

        for(int adj:con[nod])
        {
            if(!iss[adj] && direct[adj] > direct[nod] + 1)
            {
                direct[adj] = direct[nod] + 1;
                dq.push_back(adj);
            }
        }
    }
    for(int i=1;i<=n;i++)
        for(int adj:con[i])
            rez[adj] = min(rez[adj], direct[i] + 1);

    for(int i=1;i<=n;i++)
        rez[i] = min(rez[i], direct[i]);
}

int dist[50005];
void calc_dist(int cost_first, int stop_cost)//optimize with 2 queues instead of a pq-------------------------------------------
{
    for(int i=1;i<=n;i++)
        dist[i] = INF;

    for(int i=1;i<=n;i++)
    {
        if(direct[i] == INF)
            continue;
        for(int adj:con[i])
        {
            if(iss[adj])
            {
                dist[adj] = min(dist[adj], cost_first + (direct[i] + 1));
            }
        }
    }

    deque<int> dq, dq2;
    for(int i=1;i<=n;i++)
        if(dist[i] < INF)
            dq.push_back(i);
    while(!dq.empty() || !dq2.empty())
    {
        int nod = -1;
        if(!dq.empty() && (dq2.empty() || dist[dq.front()] <= dist[dq2.front()]))
        {
            nod = dq.front();
            dq.pop_front();
        }
        else
        {
            assert(!dq2.empty());
            nod = dq2.front();
            dq2.pop_front();
        }
        
        for(int adj:con[nod])
        {
            if(iss[adj])
            {
                rez[adj] = min(rez[adj], dist[nod] + 1);

                if(dist[adj] > dist[nod] + stop_cost)
                {
                    dist[adj] = dist[nod] + stop_cost;
                    dq2.push_back(adj);
                }
            }
            else
            {
                if(dist[adj] > dist[nod] + 1)
                {
                    dist[adj] = dist[nod] + 1;
                    dq.push_back(adj);
                }
            }
        }
    }
    for(int i=1;i<=n;i++)
        rez[i] = min(rez[i], dist[i]);
}

void solve_small_k()
{
    for(int i=1;i<=n;i++)
        rez[i] = INF;

    calc_directly();

    calc_11();
    calc_closest1();

    for(int i=1;i<=n;i++)
        if(dist1[i] == 0)
            dist1[i] = 2;

    //for(int i=1;i<=n;i++) cerr<<i<<": "<<dist1[i]<<" "<<best11[i]<<" dist1 & best11\n";

    //fix the nr of people that use 11------------------------------------
    vector<pair<int,int>> ord;
    for(int i=2;i<=k;i++)
    {
        ord.push_back({best11[init[i]] - dist1[init[i]], init[i]});
    }
    sort(ord.begin(), ord.end());


    for(int nr11=0;nr11<=k-1;nr11++)
    {
        int cost_first = 0, stop_cost = 1;
        bool good = 1;
        for(int i=0;i<nr11;i++)//take these as 11
        {
            int x = ord[i].second;
            if(best11[x] == INF)
            {
                good = 0;
                break;
            }
            cost_first += best11[x] + 1;
            stop_cost += 1;
        }
        for(int i=nr11;i<ord.size();i++)//take these as 1
        {
            int x = ord[i].second;
            if(dist1[x] == INF)
            {
                good = 0;
                break;
            }
            cost_first += dist1[x];
            stop_cost += 2;
        }
        if(good)
        {
            //cerr<<cost_first<<" "<<stop_cost<<" costs\n";
            calc_dist(cost_first, stop_cost);
        }
    }

    for(int i=1;i<=n;i++)
    {
        assert(rez[i] < INF);
        cout<<rez[i]<<"\n";
    }
}

void solve_big_k()
{
    
}

signed main()
{
    ios_base::sync_with_stdio(0);cin.tie(0);
    cin>>n>>m>>k;
    int u,v;
    for(int i=1;i<=m;i++)
    {
        cin>>u>>v;
        con[u].push_back(v);
        con[v].push_back(u);
    }
    string s;
    cin>>s;
    assert(s.size() == n);
    for(int i=0;i<s.size();i++)
    {
        if(s[i] == '1')
            iss[i+1] = 1;
        else
            iss[i+1] = 0;
    }
    for(int i=1;i<=k;i++)
        cin>>init[i];

    if(k <= 500 || 1)
    {
        solve_small_k();
    }
    else
    {
        solve_big_k();
    }

    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...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...