답안 #990837

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
990837 2024-05-31T13:31:13 Z andrei_iorgulescu Cities (BOI16_cities) C++14
74 / 100
2969 ms 37736 KB
#include <bits/stdc++.h>

using namespace std;

#define int long long

int inf = 1e18;

int n,k,m;
vector<int> imp;
vector<pair<int,int>> g[200005];
int dp[200005][16];
vector<int> d[5];

vector<int> dijkstra(int nod0)
{
    vector<int> dist(n + 1);
    for (int i = 1; i <= n; i++)
        dist[i] = inf;
    priority_queue<pair<int,int>> pq;
    pq.push({0,nod0});
    while (!pq.empty())
    {
        int nod = pq.top().second,cost = -pq.top().first;
        pq.pop();
        if (dist[nod] == inf)
        {
            dist[nod] = cost;
            for (auto vecin : g[nod])
            {
                pq.push({-(vecin.second + cost),vecin.first});
            }
        }
    }
    return dist;
}

signed main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    cin >> n >> k >> m;
    for (int i = 1; i <= k; i++)
    {
        int x;
        cin >> x;
        imp.push_back(x);
    }
    for (int i = 1; i <= m; i++)
    {
        int x,y,z;
        cin >> x >> y >> z;
        g[x].push_back({y,z});
        g[y].push_back({x,z});
    }
    k--;
    for (int i = 0; i <= k; i++)
        d[i] = dijkstra(imp[i]);
    for (int mask = 1; mask < (1 << k); mask++)
    {
        for (int nod = 1; nod <= n; nod++)
        {
            dp[nod][mask] = inf;
            for (int mask2 = 1; mask2 <= mask; mask2++)
            {
                if ((mask & mask2) != mask2)
                    continue;
                int lft = 0;
                for (int bit = 0; bit < k; bit++)
                {
                    if ((1 << bit) & mask2)
                        lft += d[bit][nod];
                }
                dp[nod][mask] = min(dp[nod][mask],dp[nod][mask - mask2] + lft);
            }
        }
        for (int nod = 1; nod <= n; nod++)
        {
            vector<vector<int>> dpp;
            dpp.resize(g[nod].size());
            for (int i = 0; i < g[nod].size(); i++)
                dpp[i].resize((1 << k));
            for (int i = 0; i < g[nod].size(); i++)
                for (int j = 0; j < (1 << k); j++)
                    dpp[i][j] = inf;
            for (int i = 0; i < g[nod].size(); i++)
            {
                if (i == 0)
                {
                    for (int j = 0; j < (1 << k); j++)
                    {
                        if ((j & mask) != j or (j == mask))
                            continue;
                        if (j != 0)
                            dpp[i][j] = dp[g[nod][0].first][j] + g[nod][0].second;
                    }
                }
                else
                {
                    for (int j = 0; j < (1 << k); j++)
                    {
                        if ((j & mask) != j)
                            continue;
                        dpp[i][j] = dpp[i - 1][j];
                        if (j != 0)
                        {
                            for (int jj = 1; jj < (1 << k); jj++)
                            {
                                if ((j & jj) != jj or (jj == mask))
                                    continue;
                                dpp[i][j] = min(dpp[i][j],dpp[i - 1][j - jj] + g[nod][i].second + dp[g[nod][i].first][jj]);
                            }
                        }
                    }
                }
            }
            dp[nod][mask] = min(dp[nod][mask],dpp[(int)g[nod].size() - 1][mask]);
        }
        vector<pair<int,int>> ord;
        for (int nod = 1; nod <= n; nod++)
            ord.push_back({dp[nod][mask],nod});
        sort(ord.begin(),ord.end());
        for (auto it : ord)
        {
            for (auto vecin : g[it.second])
            {
                dp[it.second][mask] = min(dp[it.second][mask],vecin.second + dp[vecin.first][mask]);
            }
        }
        ord.clear();
        for (int dub = 0; dub <= 10; dub++)
        {
            for (int nod = 1; nod <= n; nod++)
                ord.push_back({dp[nod][mask],nod});
            sort(ord.begin(),ord.end());
            for (auto it : ord)
            {
                for (auto vecin : g[it.second])
                {
                    dp[it.second][mask] = min(dp[it.second][mask],vecin.second + dp[vecin.first][mask]);
                }
            }
            ord.clear();
        }
    }
    int ans = inf;
    for (int i = 1; i <= n; i++)
        ans = min(ans,d[k][i] + dp[i][(1 << k) - 1]);
    //if (ans < dp[imp[k]][(1 << k) - 1])
      //  assert(false);
    cout << ans;
    return 0;
}

/*
4 2 6
1 3
1 2 4
1 3 9
1 4 6
2 3 2
2 4 5
3 4 8
*/

/**
as vrea sa imi fac un dp[nod][mask] = presupunand ca am plecat din imp[0] si am drum spre nod, cat imi mai ia ca sa ma conectez cu nod de mask
1.dp[nod][mask] ar putea fi dp[nod][mask2], mask2 inclus in mask cu tranzitia dp[nod][mask2] + sum(dist(nd,nod)) cu nd special in mask - mask2
acum sa presupun ca nu leg nodul nod de cnv in mod direct
2.dp[nod][mask] ar putea fi sum(dp[vec][mask_vec] + cost_edge_nod_vec) cu reuniune(mask_vec) = mask, mask_vec disjuncte (caz pe care iau macar 2 vecini)
3.dp[nod][mask] = cost_edge_nod_vec + dp[vec][mask], pe care ordinea in care calculez e gen dupa dp-uri inainte de a lua cazul asta
Complexitate: O(intra in timp)
**/

Compilation message

cities.cpp: In function 'int main()':
cities.cpp:82:31: warning: comparison of integer expressions of different signedness: 'long long int' and 'std::vector<std::pair<long long int, long long int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   82 |             for (int i = 0; i < g[nod].size(); i++)
      |                             ~~^~~~~~~~~~~~~~~
cities.cpp:84:31: warning: comparison of integer expressions of different signedness: 'long long int' and 'std::vector<std::pair<long long int, long long int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   84 |             for (int i = 0; i < g[nod].size(); i++)
      |                             ~~^~~~~~~~~~~~~~~
cities.cpp:87:31: warning: comparison of integer expressions of different signedness: 'long long int' and 'std::vector<std::pair<long long int, long long int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   87 |             for (int i = 0; i < g[nod].size(); i++)
      |                             ~~^~~~~~~~~~~~~~~
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 5212 KB Output is correct
2 Correct 1 ms 5212 KB Output is correct
3 Correct 2 ms 5212 KB Output is correct
4 Correct 1 ms 5212 KB Output is correct
5 Correct 1 ms 5212 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 668 ms 35984 KB Output is correct
2 Correct 667 ms 35308 KB Output is correct
3 Correct 374 ms 31656 KB Output is correct
4 Correct 296 ms 30256 KB Output is correct
5 Correct 305 ms 35880 KB Output is correct
6 Correct 169 ms 28668 KB Output is correct
7 Correct 4 ms 5464 KB Output is correct
8 Correct 3 ms 5468 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 8 ms 5724 KB Output is correct
2 Correct 7 ms 5728 KB Output is correct
3 Correct 6 ms 5660 KB Output is correct
4 Correct 6 ms 5468 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 1349 ms 36888 KB Output is correct
2 Correct 1265 ms 35940 KB Output is correct
3 Correct 828 ms 31932 KB Output is correct
4 Correct 932 ms 25624 KB Output is correct
5 Correct 576 ms 30952 KB Output is correct
6 Correct 505 ms 31272 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 2969 ms 37736 KB Output is correct
2 Incorrect 2927 ms 37624 KB Output isn't correct
3 Halted 0 ms 0 KB -