Pagini recente » Cod sursa (job #1680738) | Cod sursa (job #375942) | Cod sursa (job #435856) | Cod sursa (job #3357155) | Cod sursa (job #3357162)
#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;
}