제출 #1328609

#제출 시각아이디문제언어결과실행 시간메모리
1328609lywoemConstruction Project 2 (JOI24_ho_t2)C++20
100 / 100
167 ms26496 KiB
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define l(a, b, i) for (ll i = a; i < b; i++)
#define rl(a, b, i) for (ll i = a; i >= b; i--)
#define vpair vector<pair<ll, ll>>
#define inf LLONG_MAX
#define ninf LLONG_MIN

ll N, M, S, T, L, K, A, B, C;
struct Edge {
    ll to, W;
};

vector<vector<Edge>> adjlist;
vector<bool> visited;
vector<ll> dist; // array này sẽ là ans của mình á :>

void dijkstra(ll start) { // lấy 1 parameter duy nhất là source node
    visited.assign(N+1, false);
    dist.assign(N+1, inf);
    priority_queue<pair<ll, ll>, vector<pair<ll, ll>>, greater<pair<ll, ll>>> pq;

    dist[start] = 0; // initialise cái path từ source node đến chính nó là 0
    pq.push({0, start});

    while(!pq.empty()) {
        ll node = pq.top().second;
        pq.pop();

        if (!visited[node]) {
            visited[node] = true;

            for (const Edge &e : adjlist[node]) {
                if (dist[e.to] > dist[node] + e.W) { // nếu path đến e.to hiện tại > path mới thì update
                    dist[e.to] = dist[node] + e.W;
                    pq.push({dist[e.to], e.to});
                }
            }
        }
    }
}

int main() {
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    cin >> N >> M >> S >> T >> L >> K;
    adjlist.resize(N + 1); 

    l(0, M, i) {
        cin >> A >> B >> C;
        adjlist[A].push_back({B, C});
        adjlist[B].push_back({A, C});
    }

    dijkstra(S); 
    vector<pair<ll, ll>> dist1(N + 1); // đi từ S về T
    //vector<ll> distS = dist;
    l(1, N + 1, i) dist1[i] = {dist[i], i};
    
    if (dist1[T].first <= K) { // nếu chưa construct gì đã thỏa mãn thì construct kiểu quái gì cũng ok
        cout << N * (N - 1) / 2; 
        return 0; 
    }

    dijkstra(T);
    vector<pair<ll, ll>> dist2(N + 1); // đi từ T về S
    vector<ll> distT = dist; // cái vector này giữ nguyên thứ tự, nên distT[v] vẫn là shortest distance từ T đến v
    l(1, N + 1, i) dist2[i] = {dist[i], i};
    
    // Khi construct đường u <-> v thì mình sẽ đi kiểu S -> u -> v -> T
    ll maxcost = K - L; // Max cost (S -> u) + (v -> T), vì mình phải chừa ít nhất cost L cho (u -> v)

    sort(dist1.begin() + 1, dist1.end());
    sort(dist2.begin() + 1, dist2.end());

    ll ans = 0;
    l(1, N + 1, i) {
        if (dist1[i].first == inf) continue;
    
        ll need = maxcost - dist1[i].first;
        ll u = dist1[i].second;
        if (need < 0) continue;

        // pointer đến số đầu tiên trong dist[2] mà lớn hơn max length được phép của T -> v
        auto pos = upper_bound(dist2.begin() + 1, dist2.end(), make_pair(need, inf)); 
        ll cnt = pos - (dist2.begin() + 1); // đếm xem từ đầu dãy dist2 đến cái pointer đó là nhiu số

        // Tại mình dùng ub á, nên có thể pos sẽ point to cái node unreachable (inf) vì nhỡ inf là số đầu tiên > need :) 
        if (cnt > 0 && dist2[cnt].first == inf) cnt--; 
        // Vì nhỡ shortest path từ T -> u <= need, nghĩa là mình đã thêm cái đường u -> u vô cnt :D
        if (distT[u] <= need) cnt--; 

        ans += cnt;
    }

    cout << ans;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...