Skip to content

Instantly share code, notes, and snippets.

@lomnom
Last active August 6, 2025 08:38
Show Gist options
  • Select an option

  • Save lomnom/56ee98dd7afa5831b2ca36d389657b9f to your computer and use it in GitHub Desktop.

Select an option

Save lomnom/56ee98dd7afa5831b2ca36d389657b9f to your computer and use it in GitHub Desktop.
Pset 9 solutions

Dijkstra

#include <iostream>
#include <queue>
#include <vector>
#include <limits.h>

using namespace std;

typedef long long int ll;
typedef pair<ll, ll> pll;

int main(){
    cin.tie(0);
    cout.sync_with_stdio(false);

    ll N, M;
    cin >> N >> M;

    vector<vector<pll> > adj_list;
    adj_list.resize(N);
    for (ll i = 0; i < M; i++){
        ll a, b, w;
        cin >> a >> b >> w;
        a--; b--;
        adj_list[a].push_back({b, w});
        adj_list[b].push_back({a, w});
    }

    vector<ll> dist;
    dist.resize(N, LLONG_MAX);
    dist[0] = 0;

    // Dijkstra's algo
    priority_queue<pll, vector<pll>, greater<pll>> pq;
    pq.push({0, 0});

    while (!pq.empty()) {
        auto [d, u] = pq.top(); pq.pop();

        if (d > dist[u]) continue; // stale entry

        for (auto [v, w] : adj_list[u]) {
            if (dist[v] > dist[u] + w) {
                dist[v] = dist[u] + w;
                pq.push({dist[v], v});
            }
        }
    }

    if (dist[N - 1] == LLONG_MAX){
        cout << -1;
    } else {
        cout << dist[N-1];
    }

    return 0;
}

mrt

#include <iostream>
#include <queue>
#include <vector>

using namespace std;

typedef long long int ll;
typedef pair<ll, ll> pll;

vector<vector<pll> > adj_list;
vector<vector<ll> > dist;
ll N;

#define INF 1000000001

void floyd() {
    for (int i = 0; i < N; i++) {
        for (auto neighbour: adj_list[i]){
            dist[i][neighbour.first] = neighbour.second; // adj list is i -> neighbour, dist[from][to]
        }
        dist[i][i] = 0;
    }
    for (int mid = 0; mid < N; mid++) {
        for (int u = 0; u < N; u++) {
            for (int v = 0; v < N; v++) {
                if (dist[u][mid] + dist[mid][v] < dist[u][v]) { // update edge
                    dist[u][v] = dist[u][mid] + dist[mid][v];
                }
            }
        }
    }
}

int main(){
    cin.tie(0);
    cout.sync_with_stdio(false);

    ll M, Q;
    cin >> N >> M >> Q;

    adj_list.resize(N);
    for (ll i = 0; i < M; i++){
        ll a, b, w;
        cin >> a >> b >> w;
        adj_list[a].push_back({b, w});
        adj_list[b].push_back({a, w});
    }

    dist.resize(N);
    for (ll i = 0; i<N; i++){
        dist[i].resize(N, INF);
    }

    floyd();

    for (ll i = 0; i<Q; i++){
        ll a, b;
        cin >> a >> b;
        if (dist[a][b] == INF){
            cout << -1 << '\n';
        } else {
            cout << dist[a][b] << '\n';
        }
    }

    return 0;
}

employee

#include <iostream>
#include <vector>
using namespace std;

typedef long long ll;

ll deepest = 0;

vector<vector<ll> > adj; // Adj list where nodes[i] -> subordinates of i
vector<bool> visited;
void dfs(ll node, ll depth) {
    deepest = max(depth, deepest);
    visited[node] = true;

    for (auto neighbour: adj[node]){
        if (!visited[neighbour]) {
            dfs(neighbour, depth + 1);
        }
    }
}


signed main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    // ================ TAKE INPUT
    ll N, E;
    cin >> N;

    adj.resize(N);
    visited.resize(N, false);
    for (ll i = 1; i <= N-1; i++) {
        ll boss_of_i;
        cin >> boss_of_i;
        adj[boss_of_i].push_back(i);
    }
    
    dfs(0, 1); // 0 is the root.
    cout << deepest;

    return 0;
}

knightmoves

#include <iostream>
#include <vector>
#include <queue>
#include <unordered_set>
using namespace std;

typedef long long ll;

typedef pair<ll, ll> coord_t;
#define X .first
#define Y .second

struct pair_hash{
    template <class T1, class T2>
    std::size_t operator() (const std::pair<T1, T2> &pair) const {
        return std::hash<T1>()(pair.first) ^ std::hash<T2>()(pair.second);
    }
};

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    // Taking input
    ll board_size;
    cin >> board_size;

    coord_t init;
    cin >> init X >> init Y;
    coord_t target;
    cin >> target X >> target Y;

    ll forbid_n;
    cin >> forbid_n;
    unordered_set<coord_t, pair_hash> forbids;
    for (ll i = 0; i<forbid_n; i++){
        coord_t forbid;
        cin >> forbid X >> forbid Y;
        forbids.insert(forbid);
    }

    // Legal moves
    #define MOVES 8
    vector<ll> dx = {-1, +1, -1, +1, -2, -2, +2, +2};
    vector<ll> dy = {-2, -2, +2, +2, -1, +1, -1, +1};

    // BFS init.
    unordered_set<coord_t, pair_hash> visited; // if it is in this, it is visited already.
    queue< pair<coord_t, ll> > to_explore; // {to explore, moves made to get there};

    // BIG ASSUMPTION: initial is not among forbidden.

    if (init == target){
        cout << 0;
        return 0;
    }
    visited.insert({0, 0});
    to_explore.push({init, 0});

    while (!to_explore.empty()){
        auto [exploring, moves_to_here] = to_explore.front();
        ll moves_to_visiting = moves_to_here + 1;
        to_explore.pop();
        for (ll i = 0; i < MOVES; i++){
            coord_t visiting = {exploring X + dx[i], exploring Y + dy[i]};

            // Do not visit if out of board or visited or forbidden.
            if (visiting X < 0 or visiting X > board_size or 
                visiting Y < 0 or visiting Y > board_size or
                visited.find(visiting) != visited.end() or
                forbids.find(visiting) != forbids.end()){
                continue;
            }

            // Visit
            if (visiting == target){
                cout << moves_to_visiting;
                return 0;
            } 
            visited.insert(visiting);

            // Mark to explore.
            to_explore.push({visiting, moves_to_visiting}); 
        }
    }

    // if it got here, bfs terminated after doing all possibilities
    cout << -1;

    return 0;
}

erp

#include <iostream>
#include <vector>
#include <queue>
#include <climits>
using namespace std;

typedef long long ll;
typedef pair<ll, ll> pll;

// use & so that its pass-by-reference
vector<ll> dijkstra(vector< vector<pll> >& adj, ll source){
    ll N = adj.size();

    vector<ll> dist;
    dist.resize(N, LLONG_MAX);
    dist[source] = 0;

    priority_queue<pll, vector<pll>, greater<pll>> pq;
    pq.push({0, source}); // (distance, node)

    while (!pq.empty()) {
        auto [d, u] = pq.top(); pq.pop();

        if (d > dist[u]) continue; // stale entry

        for (auto [v, w] : adj[u]) {
            if (dist[v] > dist[u] + w) {
                dist[v] = dist[u] + w;
                pq.push({dist[v], v});
            }
        }
    }

    return dist;
}


int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    ll nodes_n, edges_n;
    cin >> nodes_n >> edges_n;

    vector< vector<pll> > adj;
    adj.resize(nodes_n);

    for (ll i = 0; i<edges_n; i++){
        ll a, b, f;
        cin >> a >> b >> f;
        adj[a].push_back({b, f});
        adj[b].push_back({a, f});
    }

    vector<ll> dist_start = dijkstra(adj, 0);
    vector<ll> dist_end = dijkstra(adj, nodes_n - 1);

    ll original_best = dist_start[nodes_n - 1];

    ll queries_n;
    cin >> queries_n;
    for (ll q = 0; q<queries_n; q++){
        ll a, b;
        cin >> a >> b;

        // We need to find the shortest path which passes through AB
        // Then, we get the cost of the path excluding AB.

        ll constant_cost = LLONG_MAX;
        if (dist_start[a] != LLONG_MAX && dist_end[b] != LLONG_MAX){
            constant_cost = min(constant_cost, dist_start[a] + dist_end[b]);
        }
        if (dist_start[b] != LLONG_MAX && dist_end[a] != LLONG_MAX){
            constant_cost = min(constant_cost, dist_start[b] + dist_end[a]);
        }

        if (constant_cost == LLONG_MAX){
            // If this is the case, there exists no path from start to end which passes thru AB.
            cout << -1 << '\n';
            continue;
        }

        // non-negative ERP fee (≥ $0)
        ll lower_bound = constant_cost; // (fee = 0)
        if (lower_bound >= original_best){ // ie. cannot be improved
            cout << -1 << '\n';
            continue;
        }

        // Can be improved
        cout << original_best - constant_cost - 1 << '\n';
    }

    return 0;
}

boundlessboxes

#include <iostream>
#include <vector>
#include <queue>
using namespace std;

typedef long long ll;

typedef pair<ll, ll> coord_t;
#define R .first
#define C .second

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    // Taking input
    ll rows, cols;
    cin >> rows >> cols;

    ll cells_n;
    cin >> cells_n;

    // BFS init.
        #define visited_1idx(row, col) visited[(row)-1][(col)-1]
        vector< vector<bool> > visited; // if visited[row][cols], visited alr.
        visited.resize(rows);
        for (ll i = 0; i<rows; i++){
            visited[i].resize(cols, false); 
        }
        queue< pair<coord_t, ll> > to_explore; // {to explore, number of shades used so far};
    // BFS init end

    // Counter
    ll answer = 0;

    for (ll i = 0; i<cells_n; i++){
        coord_t seed;
        cin >> seed R >> seed C;

        to_explore.push({seed, 1});

        // Visit seed
        visited_1idx(seed R, seed C) = true; // REMEMBER TS OMG
        answer = max(answer, 1LL);
    }

    // Legal moves
    #define MOVES 8
    vector<ll> dr = {-1, -1, -1,  0,  0, +1, +1, +1};
    vector<ll> dc = {-1,  0, +1, -1, +1, -1,  0, +1};

    // BFS
    while (!to_explore.empty()){
        auto [exploring, shades_so_far] = to_explore.front();
        ll shades_at_visiting = shades_so_far + 1;
        to_explore.pop();

        for (ll i = 0; i < MOVES; i++){
            coord_t visiting = {exploring R + dr[i], exploring C + dc[i]};

            // Do not visit if out of board or visited
            if (visiting R <= 0 or visiting R > rows or 
                visiting C <= 0 or visiting C > cols or
                visited_1idx(visiting R,visiting C)){
                continue;
            }

            // Visit
            visited_1idx(visiting R, visiting C) = true;
            answer = max(answer, shades_at_visiting);

            // Mark to explore.
            to_explore.push({visiting, shades_at_visiting}); 
        }
    }

    // if it got here, bfs terminated after doing all possibilities
    cout << answer;

    return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment