Cod sursa(job #3357162)

Utilizator parus_majorParus Major parus_major Data 6 iunie 2026 18:10:30
Problema Critice Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 4.08 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <algorithm>

using namespace std;

struct Edge {
    int to;
    int cap;
    int flow;
    int rev_idx;
};

int N, M;
vector<vector<Edge>> adj;
vector<pair<int, int>> original_edges;
vector<int> level;
vector<int> next_edge;
vector<bool> vis_S, vis_T;

// Pasul BFS din Dinic: construieste graful pe niveluri
bool bfs_dinic(int source, int sink) {
    fill(level.begin(), level.end(), -1);
    level[source] = 0;
    queue<int> q;
    q.push(source);

    while (!q.empty()) {
        int u = q.front();
        q.pop();

        for (const auto& e : adj[u]) {
            if (level[e.to] == -1 && e.cap - e.flow > 0) {
                level[e.to] = level[u] + 1;
                q.push(e.to);
            }
        }
    }
    return level[sink] != -1;
}

// Pasul DFS din Dinic: trimite flux prin graful pe niveluri
int dfs_dinic(int u, int sink, int pushed) {
    if (pushed == 0) return 0;
    if (u == sink) return pushed;

    // next_edge[u] ne ajuta sa nu reluam aceleasi muchii saturate de la inceput
    for (int& cid = next_edge[u]; cid < adj[u].size(); ++cid) {
        Edge& e = adj[u][cid];
        int tr = e.to;

        if (level[u] + 1 != level[tr] || e.cap - e.flow == 0) continue;

        int tr_pushed = dfs_dinic(tr, sink, min(pushed, e.cap - e.flow));
        if (tr_pushed == 0) continue;

        e.flow += tr_pushed;
        adj[tr][e.rev_idx].flow -= tr_pushed;
        return tr_pushed;
    }
    return 0;
}

// Functia principala Dinic
void dinic(int source, int sink) {
    level.resize(N + 1);
    next_edge.resize(N + 1);

    while (bfs_dinic(source, sink)) {
        fill(next_edge.begin(), next_edge.end(), 0);
        while (int pushed = dfs_dinic(source, sink, 2e9)) {
            // Trimitem flux pana cand nu mai se poate in acest strat
        }
    }
}

// Identificam nodurile accesibile din sursa in graful rezidual final
void bfs_S(int source) {
    vis_S.assign(N + 1, false);
    queue<int> q;
    q.push(source);
    vis_S[source] = true;

    while (!q.empty()) {
        int u = q.front();
        q.pop();

        for (const auto& e : adj[u]) {
            if (!vis_S[e.to] && e.cap - e.flow > 0) {
                vis_S[e.to] = true;
                q.push(e.to);
            }
        }
    }
}

// Identificam nodurile din care se poate ajunge la destinatie in graful rezidual final
void bfs_T(int sink) {
    vis_T.assign(N + 1, false);
    queue<int> q;
    q.push(sink);
    vis_T[sink] = true;

    while (!q.empty()) {
        int u = q.front();
        q.pop();

        for (const auto& e : adj[u]) {
            int rev_idx = e.rev_idx;
            // Mergem inapoi pe muchiile care au capacitate reziduala ramasa pe sensul direct
            if (!vis_T[e.to] && adj[e.to][rev_idx].cap - adj[e.to][rev_idx].flow > 0) {
                vis_T[e.to] = true;
                q.push(e.to);
            }
        }
    }
}

int main() {
    ifstream fin("critice.in");
    ofstream fout("critice.out");

    if (!fin) return 0;

    fin >> N >> M;
    adj.resize(N + 1);
    original_edges.resize(M + 1);

    for (int i = 1; i <= M; ++i) {
        int u, v, c;
        fin >> u >> v >> c;
        original_edges[i] = { u, v };

        // Structura graf neorientat
        adj[u].push_back({ v, c, 0, (int)adj[v].size() });
        adj[v].push_back({ u, c, 0, (int)adj[u].size() - 1 });
    }

    // Pasul 1: Flux Maxim cu Dinic
    dinic(1, N);

    // Pasul 2: Gasirea componentelor S si T
    bfs_S(1);
    bfs_T(N);

    // Pasul 3: Colectarea muchiilor critice
    vector<int> critical_edges;
    for (int i = 1; i <= M; ++i) {
        int u = original_edges[i].first;
        int v = original_edges[i].second;

        if ((vis_S[u] && vis_T[v]) || (vis_S[v] && vis_T[u])) {
            critical_edges.push_back(i);
        }
    }

    fout << critical_edges.size() << "\n";
    for (int id : critical_edges) {
        fout << id << "\n";
    }

    return 0;
}