Cod sursa(job #2244738)

Utilizator SqueekDanielTodasca Daniel SqueekDaniel Data 23 septembrie 2018 15:51:46
Problema Critice Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.88 kb
#include <bits/stdc++.h>

#define MaxN 1005
#define MaxM 10005
#define inf  (int)(1e9)
#define mp   std::make_pair

std::ifstream InFile("critice.in");
std::ofstream OutFile("critice.out");

struct GraphStruct {
    int N, M;
    struct NodeStruct {
        struct ADCStruct {
            int Node,       // Unde ajunge muchia
                EdgeIndex;  // Index-ul pentru muchie, dupa cum a fost citita
            ADCStruct (int Node, int EdgeIndex) {
                this->Node = Node; this->EdgeIndex = EdgeIndex;
            }
        };
        std::list <ADCStruct> ADC;
    }   Node[MaxN];

    std::pair <int, int> ReadEdge[MaxM];
    int EdgeIndex[MaxN][MaxN], Capacity[2*MaxM],
        Flow[2*MaxM];       // Flux-ul pe care il avem pentru muchia cu index i

    void AddEdge(int x, int y, int res, int i) {                    // Muchiile impare sunt muchiile pozitive x->y, muchiile pare cele negative x<-y
        Node[x].ADC.push_back(NodeStruct::ADCStruct(y, 2*i+1));     // Ca sa transform muchia i dupa cum am citit-o la inceput fac (i+1)/2
        Node[y].ADC.push_back(NodeStruct::ADCStruct(x, 2*i+2));
        Capacity[2*i+1] = Capacity[2*i+2] = res;
        Flow[2*i+1] = Flow[2*i+2] = 0;
        EdgeIndex[x][y] = 2*i+1;
        EdgeIndex[y][x] = 2*i+2;

        ReadEdge[i+1] = mp(x, y);
    }

    int Visit[MaxN];
    void DFS(int Start, int Value) {
        Visit[Start] = Value;
        for (auto ADC:Node[Start].ADC)
            if (!Visit[ADC.Node])
                if (Flow[ADC.EdgeIndex] != abs(Capacity[ADC.EdgeIndex]))
                    DFS (ADC.Node, Value);
    }

    int Previous[MaxN];
    bool BFSAugmentingPath() {
        for (int i=0; i<N; i++)
            Previous[i+1] = 0;

        std::queue <int> BFSQueue;
        BFSQueue.push(1);
        Previous[1] = -1;

        int Front;
        while(!BFSQueue.empty()) {
            Front = BFSQueue.front();
            BFSQueue.pop();

            if(Front == N) continue;
            for (auto ADC:Node[Front].ADC) {
                if (Previous[ADC.Node]!=0 || Flow[ADC.EdgeIndex] == Capacity[ADC.EdgeIndex]) continue;
                BFSQueue.push(ADC.Node);
                Previous[ADC.Node] = Front;
            }
        }   return (Previous[N] > 0);
    }

    void EdmondKarp() {
        while(BFSAugmentingPath()) {
            for (auto ADC:Node[N].ADC) {  // Luam acum toate path-urile gasite
                if (Flow[ADC.EdgeIndex] == Capacity[ADC.EdgeIndex] || !Previous[ADC.Node]) continue;
                int MinFlow = inf;

                Previous[N] = ADC.Node;
                int p; p = N;
                while (p!=1)
                    MinFlow = std::min (MinFlow, Capacity[EdgeIndex[Previous[p]][p]] - Flow[EdgeIndex[Previous[p]][p]]),
                    p = Previous[p];

                if (MinFlow == 0) continue;
                p = N;
                while (p!=1)
                    Flow[EdgeIndex[Previous[p]][p]] += MinFlow,
                    Flow[EdgeIndex[p][Previous[p]]] -= MinFlow,
                    p = Previous[p];
            }
        }
    }
}   Graph;

std::vector <int> CriticalEdges;

void Citire() {
    InFile >> Graph.N >> Graph.M;

    for (int i=0, x, y, res; i<Graph.M; i++)
        InFile >> x >> y >> res,
        Graph.AddEdge(x, y, res, i);
}
void Rezolvare() {
    Graph.EdmondKarp();

    Graph.DFS(1, 1);
    Graph.DFS(Graph.N, 2);

    for (int i=0; i<Graph.M; i++)
        if (Graph.Visit[Graph.ReadEdge[i+1].first] && Graph.Visit[Graph.ReadEdge[i+1].second] && Graph.Visit[Graph.ReadEdge[i+1].first] != Graph.Visit[Graph.ReadEdge[i+1].second])
            CriticalEdges.push_back(i+1);

    OutFile << CriticalEdges.size() << '\n' ;
    for (int i=0; i<CriticalEdges.size(); i++)
        OutFile << CriticalEdges[i] << '\n' ;
}

int main()
{
    Citire();
    Rezolvare();

    return 0;
}