제출 #1302398

#제출 시각아이디문제언어결과실행 시간메모리
1302398TVSownCities (BOI16_cities)C++20
100 / 100
2240 ms70532 KiB
///*** Sown_Vipro ***///
/// ->NHI QUOC GIA<- ///

#include<bits/stdc++.h>
using namespace std;
//#pragma GCC optimize ("O3")
//#pragma GCC optimize ("unroll-loops")
//#pragma GCC target("popcnt")
#define F first
#define S second
#define pb push_back
#define pi pair<int, int>
#define pii pair<int, pair<int, int> >
#define FOR(i, a, b) for(int i = a; i <= b; ++i)
#define REP(i, a, b) for(int i = a; i >= b; --i)
#define all(s) s.begin(), s.end()
#define szz(s) int(s.size())
const string NAME = "cities";
const int N = 3e5 + 5, MAX = 1e6, oo = 1e9 + 5, MOD = 1e9 + 7;
void maxi(int &x, int y){ if(x < y) x = y; }
void maxill(long long &x, long long y){ if(x < y) x = y; }
void mini(int &x, int y){ if(x > y) x = y; };
void minill(long long &x, long long y){ if(x > y) x = y; };
void add(int &x, int y){ x += y; x += MOD * (x < 0); x -= MOD * (x >= MOD); };
int n, k, m;
int spe[N];
struct edge{
    int u, v, w;
} e[N];

bool cmp(edge a, edge b){
    return a.w < b.w;
}

namespace sub1{
    int p[N];

    int Find(int u){
        if(u == p[u]) return u;
        return p[u] = Find(p[u]);
    }

    int Union(int u, int v){
        u = Find(u);
        v = Find(v);
        if(u == v) return 0;

        p[v] = u;
        return 1;
    }

    int vst[N];
    vector<int> adj[N];
    void dfs(int u){
        vst[u] = 1;
        for(int v : adj[u]){
            if(vst[v]) continue;
            dfs(v);
        }
    }

    void solve(){
        long long res = 1e18;

        FOR(mask, 1, (1 << n) - 1){
            int check = 1;
            FOR(i, 1, k){
                if(!(mask & (1 << spe[i] - 1))) check = 0;
            }
            if(!check) continue;


//            FOR(u, 1, n){
//                if(mask & (1 << u - 1)) cout << u << " ";
//            }
//            cout << "\n";
//            cout << mask << "\n";
            FOR(u, 1, n) p[u] = u;
            long long sum = 0;
            FOR(i, 1, m){
                int u = e[i].u, v = e[i].v, w = e[i].w;
                if((mask & (1 << u - 1)) && (mask & (1 << v - 1))){
                    if(Union(u, v)){
//                        cout << u << " " << v << " " << w << "\n";
                        sum += w;
                        adj[u].pb(v);
                        adj[v].pb(u);
                    }
                }
            }
            dfs(spe[1]);
            FOR(i, 1, k) if(!vst[spe[i]]) check = 0;
//            cout << sum << "\n";
            if(check) minill(res, sum);
            FOR(u, 1, n){
                vst[u] = 0;
                adj[u].clear();
            }
        }
        cout << res;
    }
}

namespace sub2{
    vector<vector<long long> > d(10, vector<long long> (N));
    vector<pi> adj[N];

    void dt(int S, vector<long long> &d){
        FOR(u, 1, n) d[u] = 1e18;
        priority_queue<pair<long long, int> > pq;
        pq.push({0, S});
        d[S] = 0;
        while(szz(pq)){
            int u = pq.top().S;
            long long du = -pq.top().F;
            pq.pop();

            if(du != d[u]) continue;
            for(auto [v, w] : adj[u]){
                if(du + w < d[v]){
                    d[v] = du + w;
                    pq.push({-d[v], v});
                }
            }
        }
    }

    void solve(){
        FOR(i, 1, m){
            adj[e[i].u].pb({e[i].v, e[i].w});
            adj[e[i].v].pb({e[i].u, e[i].w});
        }
        if(k == 3){
            dt(spe[1], d[1]);
            dt(spe[2], d[2]);
            dt(spe[3], d[3]);

            long long res = 1e18;
            FOR(u, 1, n){
    //            cout << u << " " << d[1][u] << " " << d[2][u] << " " << d[3][u] << "\n";
                minill(res, d[1][u] + d[2][u] + d[3][u]);
            }
            cout << res;
        }else{
            dt(spe[1], d[1]);
            dt(spe[2], d[2]);

            long long res = 1e18;
            FOR(u, 1, n){
    //            cout << u << " " << d[1][u] << " " << d[2][u] << " " << d[3][u] << "\n";
                minill(res, d[1][u] + d[2][u]);
            }
            cout << res;
        }
    }
}

namespace ac{
    long long d[N][(1 << 5) + 5];
    vector<pi> adj[N];
    void solve(){
        FOR(i, 1, m){
            adj[e[i].u].pb({e[i].v, e[i].w});
            adj[e[i].v].pb({e[i].u, e[i].w});
        }
        FOR(mask, 1, (1 << k) - 1){
            FOR(u, 1, n){
                d[u][mask] = 1e18;
            }
            int cnt = __builtin_popcount(mask);
            if(cnt == 1){
                int s = spe[__builtin_ctz(mask) + 1];
                d[s][mask] = 0;
            }else{
                FOR(u, 1, n){
                    for(int sub = (mask - 1) & mask; sub; sub = (sub - 1) & mask){
                        for(auto [v, w] : adj[u]){
                            d[u][mask] = min(d[u][mask], d[u][mask ^ sub] + d[v][sub] + w);
                        }
                    }
                }
            }
            priority_queue<pair<long long, int>, vector<pair<long long, int> >, greater<pair<long long, int> > > pq;
            FOR(u, 1, n) pq.push({d[u][mask], u});

            while(pq.size()){
                long long du = pq.top().F;
                int u = pq.top().S;
                pq.pop();
                if(du != d[u][mask]) continue;

                for(auto [v, w] : adj[u]){
                    if(d[v][mask] > d[u][mask] + w){
                        d[v][mask] = d[u][mask] + w;
                        pq.push({d[v][mask], v});
                    }
                }
            }
        }
//        cout <<
        long long res = 1e18;
        FOR(u, 1, n){
            res = min(res, d[u][(1 << k) - 1]);
        }
        cout << res;
    }
}

void solve(){
    cin >> n >> k >> m;
    FOR(i, 1, k){
        cin >> spe[i];
    }
    FOR(i, 1, m){
        int u, v, w; cin >> u >> v >> w;
        e[i] = {u, v, w};
    }
    sort(e + 1, e + 1 + m, cmp);
    if(n <= 20) sub1::solve();
    else if(k == 3) sub2::solve();
    else ac::solve();
}

signed main(){
    ios_base::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    if(fopen((NAME + ".inp").c_str(), "r")){
        freopen((NAME + ".inp").c_str(), "r", stdin);
        freopen((NAME + ".out").c_str(), "w", stdout);
    }
    int t = 1;
//    cin >> t;
    while(t--){
        solve();
    }
}

컴파일 시 표준 에러 (stderr) 메시지

cities.cpp: In function 'int main()':
cities.cpp:228:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  228 |         freopen((NAME + ".inp").c_str(), "r", stdin);
      |         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cities.cpp:229:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  229 |         freopen((NAME + ".out").c_str(), "w", stdout);
      |         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#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...