Cod sursa(job #1108421)

Utilizator toranagahVlad Badelita toranagah Data 15 februarie 2014 17:34:50
Problema Critice Scor 90
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.87 kb
#include <cstring>
#include <algorithm>
#include <fstream>
#include <iostream>
#include <queue>
#include <vector>
using namespace std;

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

const int MAX_N = 1005;
const int MAX_M = 10100;
const int INF = 1 << 30;

int N, M;
vector<int> graph[MAX_N];
pair<int, int> edges[MAX_M];
bool source_path[MAX_N];
bool sink_path[MAX_N];
int cap[MAX_N][MAX_N];
int flow[MAX_N][MAX_N];
int incoming[MAX_N];
int source, sink;
vector<int> answer;

void read_input();
void solve();
void print_output();
int maxflow();
bool find_augmenting_path();
void dfs(int start, bool path[]);
int cp(int a, int b);

int main() {
    read_input();
    solve();
    print_output();
}

void read_input() {
    fin >> N >> M;
    for (int i = 1, a, b, c; i <= M; ++i) {
        fin >> a >> b >> c;
        graph[a].push_back(b);
        graph[b].push_back(a);
        cap[a][b] = c;
        cap[b][a] = c;

        edges[i].first = a;
        edges[i].second = b;
    }
    source = 1; sink = N;
}

void solve() {
    maxflow();

    dfs(source, source_path);
    dfs(sink, sink_path);

    for (int i = 1, a, b; i <= M; ++i) {
        a = edges[i].first;
        b = edges[i].second;

        if ((source_path[a] && sink_path[b]) ||
                (sink_path[a] && source_path[b])) {
            answer.push_back(i);
        }
    }
}

void print_output() {
    fout << answer.size() << '\n';
    for (auto node : answer) {
        fout << node << '\n';
    }
}

int maxflow() {
    int result = 0;
    while (find_augmenting_path()) {
        for (auto i: graph[sink]) {
            int new_flow = cp(i, sink);
            for (int node = i; node != source; node = incoming[node]) {
                new_flow = min(new_flow, cp(incoming[node], node));
            }

            if(new_flow == 0) continue;

            flow[i][sink] += new_flow;
            flow[sink][i] -= new_flow;

            for (int node = i; node != source; node = incoming[node]) {
                flow[incoming[node]][node] += new_flow;
                flow[node][incoming[node]] -= new_flow;
            }
            result += new_flow;
        }

        memset(incoming, 0, sizeof(incoming));
    }
    return result;
}

bool find_augmenting_path() {
    queue<int> q;
    q.push(source);
    source_path[source] = 1;

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

        if (node == sink) return true;

        for (auto next: graph[node]) {
            if (!incoming[next] && cp(node, next) > 0) {
                incoming[next] = node;
                q.push(next);
            }
        }
    }
    return false;
}

void dfs(int node, bool path[]) {
    path[node] = true;
    for (auto next : graph[node]) {
        if (cp(node, next) > 0 && cp(next, node) > 0 && path[next] == false) {
            dfs(next, path);
        }
    }
}

inline int cp(int a, int b) {
    return cap[a][b] - flow[a][b];
}