제출 #834438

#제출 시각아이디문제언어결과실행 시간메모리
834438_martynasAesthetic (NOI20_aesthetic)C++11
38 / 100
751 ms77508 KiB
    #include <bits/stdc++.h>
     
    using namespace std;
     
    using ll = long long;
     
    #warning change mxn
    const int mxn = 3e5+5;
    const ll inf = 1e16;
     
    struct Edge {
        int to, id;
    };
     
    int n, m;
    int A[mxn], B[mxn];
    vector<Edge> adj[mxn];
    ll W[mxn];
    vector<Edge> adj2[mxn];
    bool isbridge[mxn], visited[mxn];
    vector<ll> from1, fromn;
     
    vector<ll> get_min_dist(int start) {
        vector<long long> dist(n+1, inf);
        priority_queue<pair<ll, int>> pq;
        dist[start] = 0;
        pq.push({-dist[start], start});;
        while(!pq.empty()) {
            ll d = -pq.top().first;
            int a = pq.top().second;
            pq.pop();
            if(dist[a] != d) continue;
            for(auto e : adj[a]) if(dist[e.to] > d+W[e.id]) {
                dist[e.to] = d+W[e.id];
                pq.push({-dist[e.to], e.to});
            }
        }
        return dist;
    }
     
     
    int tim = 0;
    int disc[mxn], low[mxn];
    void bridge_det(int u, int par) {
        visited[u] = true;
        low[u] = disc[u] = tim++;
        for(auto e : adj2[u]) if(e.to != par) {
            if(!visited[e.to]) {
                bridge_det(e.to, u);
                if(low[e.to] > disc[u]) {
                    isbridge[e.id] = true;
                }
            }
            low[u] = min(low[u], low[e.to]);
        }
    }
     
    int main(int argc, char const *argv[]) {
        cin >> n >> m;
        for(int i = 1; i <= m; i++) {
            cin >> A[i] >> B[i] >> W[i];
            adj[A[i]].push_back({B[i], i});
            adj[B[i]].push_back({A[i], i});
        }
        from1 = get_min_dist(1);
        fromn = get_min_dist(n);
        ll mxw = W[m];
        vector<ll> ans(m+1);
        for(int i = m-1; i >= 1; i--) {
            ll nw = W[i]+mxw;
            ll mndist = inf;
            mndist = min(mndist, from1[A[i]]+fromn[B[i]]+nw);
            mndist = min(mndist, from1[B[i]]+fromn[A[i]]+nw);
            ans[i] = mndist;
            mxw = max(mxw, W[i]);
        }
        // build new graph where every path is min
        for(int i = 1; i <= m; i++) {
            if(from1[A[i]]+fromn[B[i]]+W[i] == from1[n] || from1[B[i]]+fromn[A[i]]+W[i] == from1[n]) {
                adj2[A[i]].push_back({B[i], i});
                adj2[B[i]].push_back({A[i], i});
            }
        }
        // printf("new graph\n");
        // for(int i = 1; i <= n; i++) {
        //     printf("%d: ", i);
        //     for(auto e : adj2[i]) {
        //         printf("%d (%d), ", e.to, e.id);
        //     }
        //     printf("\n");
        // }
        fill(low, low+n+1, mxn);
        bridge_det(1, -1);
        // printf("bridge: ");
        // for(int i = m; i >= 1; i--) if(isbridge[i]) printf("%d ", i);
        // printf("\n");
        vector<int> cnt_to_id(m+1);
        fill(visited, visited+n+1, false);
        queue<int> q;
        visited[1] = true; q.push(1);
        int c = 0;
        while(!q.empty()) {
            int u = q.front(); q.pop();
            for(auto e : adj2[u]) if(!visited[e.to]) {
                visited[e.to] = true;
                c += isbridge[e.id];
                cnt_to_id[c] = e.id;
            }
        }
        vector<long long> dist(n+1, inf);
        vector<int> cnt(n+1);
        priority_queue<pair<pair<ll, int>, int>> pq;
        vector<Edge> used_edge; vector<int> from;
        dist[1] = 0, cnt[1] = 0;
        pq.push({{-dist[1], 1}, -1});
        vector<vector<ll>> ins(m+1), del(m+1);
        while(!pq.empty()) {
            ll d = -pq.top().first.first;
            int a = pq.top().first.second;
            int edgeidx = pq.top().second;
            pq.pop();
            if(edgeidx != -1) {
                // cerr << from[edgeidx] << " -> " << a << "\n";
                // cerr << cnt[from[edgeidx]]+isbridge[used_edge[edgeidx].id] << "; " << cnt[a] << "\n";
                if(cnt[used_edge[edgeidx].to] > cnt[from[edgeidx]]+isbridge[used_edge[edgeidx].id]) {
                    int l = cnt[from[edgeidx]]+isbridge[used_edge[edgeidx].id]+1, r = cnt[a];
                    ll val = from1[from[edgeidx]]+W[used_edge[edgeidx].id]+fromn[a];
                    // for(int i = l; i <= r; i++) {
                    //     // cerr << "modify " << cnt_to_id[i] << "\n";
                    //     ans[cnt_to_id[i]] = min(ans[cnt_to_id[i]], val);
                    // }
                    ins[l].push_back(val);
                    del[r].push_back(val);
                }
            }
            if(dist[a] != d) continue;
            // cerr << a << " " << d << "\n";
            for(auto e : adj[a]) {
                if(dist[e.to] > d+W[e.id]) {
                    cnt[e.to] = cnt[a]+isbridge[e.id];
                    dist[e.to] = d+W[e.id];
                    pq.push({{-dist[e.to], e.to}, used_edge.size()});
                    used_edge.push_back(e); from.push_back(a);
                    // cerr << "add " << from.back() << " " << used_edge.back().to << "\n";
                }
                else {
                    // cerr << a << " -> " << e.to << "\n";
                    // cerr << cnt[a]+isbridge[e.id] << "; " << cnt[e.to] << "\n";
                    if(cnt[e.to] > cnt[a]+isbridge[e.id]) {
                        int l = cnt[a]+isbridge[e.id]+1, r = cnt[e.to];
                        ll val = from1[a]+W[e.id]+fromn[e.to];
                        // for(int i = l; i <= r; i++)  {
                        //     // cerr << i << ": " << cnt_to_id[i] << "?\n";
                        //     ans[cnt_to_id[i]] = min(ans[cnt_to_id[i]], val);
                        // }
                        ins[l].push_back(val);
                        del[r].push_back(val);
                    }
                }
            }
        }
        multiset<ll> available;
        for(int i = 0; i < m; i++) {
            for(ll x : ins[i]) available.insert(x);
            if(cnt_to_id[i] != 0 && !available.empty()) {
                ans[cnt_to_id[i]] = min(ans[cnt_to_id[i]], *available.begin());
            }
            for(ll x : del[i]) available.erase(available.find(x));
        }
        ll answer = 0;
        for(int i = 1; i < m; i++) {
            // cerr << ans[i] << " ";
            answer = max(answer, isbridge[i] ? ans[i] : from1[n]);
        }
        // cerr << "\n";
        cout << answer << "\n";
        return 0;
    }

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

Aesthetic.cpp:7:6: warning: #warning change mxn [-Wcpp]
    7 |     #warning change mxn
      |      ^~~~~~~
#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...