Cod sursa(job #3270739)

Utilizator StefanMilitaruMilitaru Stefan-Octavian StefanMilitaru Data 24 ianuarie 2025 12:11:59
Problema Sortare topologica Scor 70
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 8.79 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <utility>
using namespace std;
class vertice;
class graph;
class edge {
    vertice* start;
    vertice* end;
    int weight;
    int capacity;
public:
    edge(vertice* v1, vertice* v2) : start(v1), end(v2) {}
    edge(vertice* v1, vertice* v2, int w) : start(v1), end(v2), weight(w) {}
    edge(vertice* v1, vertice* v2, int w, int c) : start(v1), end(v2), weight(w), capacity(c) {}
    void set_capacity(int cap) {capacity = cap;}
    void set_weight(int wgt) {weight = wgt;}
    int get_capacity() {return capacity;}
    int get_weight() {return weight;}
    friend ostream& operator<<(ostream& out, const graph& g);
    friend class graph;
    friend class oriented_graph;
    friend class vertice;
};
class vertice {
protected:
    int id;
    vector<edge*> edges;
public:
    vertice(int id) : id(id){}
    void add_edge(edge* e) {edges.push_back(e);}
    int get_id() {return id;}
    friend ostream& operator<<(ostream& out, const graph& g);
    friend class graph;
    friend class oriented_graph;
    friend class edge;
};
class oriented_vertice : public vertice{
    vector<edge*> in_edges;
public:
    oriented_vertice(int id) : vertice(id) {}
    void add_in_edge(edge* e) {in_edges.push_back(e);}
    friend class graph;
    friend class oriented_graph;
    friend class edge;
};
class graph {
protected:
    int nr_vertices;
    int nr_edges;
    vector<vertice*> vertices;
    vector<edge*> edges;
public:
    graph() {vertices.push_back(new vertice(0));}
    graph(int nr_vertices, int nr_edges) : nr_vertices(nr_vertices), nr_edges(nr_edges) {vertices.push_back(new vertice(0));}
    virtual void add_vertice(vertice* v) {
        vertices.push_back(v);
        nr_vertices++;
    }
    virtual void add_edge(vertice* v1, vertice* v2) {
        edge* e = new edge(v1, v2);
        v1->add_edge(e);
        v2->add_edge(e);
        edges.push_back(e);
        nr_edges++;
    }
    virtual bool edge_exists(int start, int end);
    virtual void DFS(int start, vector<int>& visited);
    virtual void DFS_start(int start);
    virtual void BFS(int start);
    friend istream& operator>>(istream& in, graph& g);
    friend ostream& operator<<(ostream& out, const graph& g);
    friend class vertice;
    friend class edge;
};
class oriented_graph : public graph {
    vector<oriented_vertice*> vertices;
public:
    oriented_graph() : graph() {vertices.push_back(new oriented_vertice(0));}
    oriented_graph(int nr_vertices, int nr_edges) : graph(nr_vertices, nr_edges) {vertices.push_back(new oriented_vertice(0));}
    void add_vertice(oriented_vertice* v) {
        vertices.push_back(v);
        nr_vertices++;
    }
    void add_edge(oriented_vertice* v1, oriented_vertice* v2) {
        edge* e = new edge(v1, v2);
        v1->add_edge(e);
        v2->add_in_edge(e);
        edges.push_back(e);
        nr_edges++;
    }
    bool edge_exists(int start, int end);
    void DFS(int start, vector<int>& visited);
    void DFS_start(int start);
    void BFS(int start);
    bool topo_sort();
    friend istream& operator>>(istream& in, oriented_graph& og);
};
bool graph :: edge_exists(int start, int end) {
    for (int i = 0; i < vertices[start]->edges.size(); i++) {
        if ((vertices[start]->edges[i]->end->get_id() == end) || (vertices[start]->edges[i]->start->get_id() == end)){
            return true;
        }
    }
    return false;
}
bool oriented_graph :: edge_exists(int start, int end) {
    for (int i = 0; i < vertices[start]->edges.size(); i++) {
        if (vertices[start]->edges[i]->end->get_id() == end) {
            return true;
        }
    }
    return false;
}
void graph :: DFS(int start, vector<int>& visited) {
    visited[start] = 1;
    cout << start << " ";
    for (int i = 0; i < vertices[start]->edges.size(); i++){
        if (visited[vertices[start]->edges[i]->start->get_id()] == 0) {
            DFS(vertices[start]->edges[i]->start->get_id(), visited);
        }
        else {
            if (visited[vertices[start]->edges[i]->end->get_id()] == 0) {
                DFS(vertices[start]->edges[i]->end->get_id(), visited);
            }
        }
    }
}
void oriented_graph :: DFS(int start, vector<int>& visited) {
    visited[start] = 1;
    cout << start << " ";
    for (int i = 0; i < vertices[start]->edges.size(); i++){
        if (visited[vertices[start]->edges[i]->end->get_id()] == 0) {
            DFS(vertices[start]->edges[i]->end->get_id(), visited);
        }
    }
}
void graph :: DFS_start(int start) {
    vector<int> visited;
    visited.resize(nr_vertices + 1);
    for (int i = 1; i <= nr_vertices; i++) {
        visited[i] = 0;
    }
    visited[start] = 1;
    DFS(start, visited);
}
void oriented_graph :: DFS_start(int start) {
    vector<int> visited;
    visited.resize(nr_vertices + 1);
    for (int i = 1; i <= nr_vertices; i++) {
        visited[i] = 0;
    }
    visited[start] = 1;
    DFS(start, visited);
}
void graph::BFS(int start) {
    queue<int> vqueue;
    vector<int> visited;
    visited.resize(nr_vertices + 1);
    for (int i = 1; i <= nr_vertices; i++) {
        visited[i] = 0;
    }
    visited[start] = 1;
    vqueue.push(start);
    while (!vqueue.empty()) {
        int curr = vqueue.front();
        cout << curr << " ";
        for (int i = 0; i < vertices[curr]->edges.size();i++) {
            if (visited[vertices[curr]->edges[i]->start->get_id()] == 0) {
                vqueue.push(vertices[curr]->edges[i]->start->get_id());
                visited[vertices[curr]->edges[i]->start->get_id()] = 1;
            }
            else {
                if (visited[vertices[curr]->edges[i]->end->get_id()] == 0) {
                    vqueue.push(vertices[curr]->edges[i]->end->get_id());
                    visited[vertices[curr]->edges[i]->end->get_id()] = 1;
                }
            }
        }
        vqueue.pop();
    }
}
void oriented_graph::BFS(int start) {
    queue<int> vqueue;
    vector<int> visited;
    visited.resize(nr_vertices + 1);
    for (int i = 1; i <= nr_vertices; i++) {
        visited[i] = 0;
    }
    visited[start] = 1;
    vqueue.push(start);
    while (!vqueue.empty()) {
        int curr = vqueue.front();
        cout << curr << " ";
        for (int i = 0; i < vertices[curr]->edges.size();i++) {
            if (visited[vertices[curr]->edges[i]->end->get_id()] == 0) {
                vqueue.push(vertices[curr]->edges[i]->end->get_id());
                visited[vertices[curr]->edges[i]->end->get_id()] = 1;
            }
        }
        vqueue.pop();
    }
}
bool oriented_graph :: topo_sort() {
    vector<int> unused_vertices;
    unused_vertices.resize(nr_vertices + 1);
    vector<oriented_vertice*> sorted_vertices;
    queue<oriented_vertice*> vqueue;
    for (int i = 1; i <= nr_vertices;  i++) {
        unused_vertices[i] = vertices[i]->in_edges.size();
        if (unused_vertices[i] == 0) {
            vqueue.push(vertices[i]);
            unused_vertices[i] = -1;
        }
    }
    while (!vqueue.empty()) {
        oriented_vertice* curr = vqueue.front();
        sorted_vertices.push_back(curr);
        for (int i = 0; i < curr->edges.size(); i++) {
            unused_vertices[curr->edges[i]->end->get_id()]--;
        }
        for (int i = 1; i <= nr_vertices;  i++) {
            if (unused_vertices[i] == 0) {
                vqueue.push(vertices[i]);
                unused_vertices[i] = -1;
            }
        }
        vqueue.pop();
    }
    if (sorted_vertices.size() != nr_vertices) {
        return false;
    }
    ofstream fout("sortaret.out");
    for (int i = 0; i < sorted_vertices.size(); i++) {
        fout << sorted_vertices[i]->get_id() << " ";
    }
    return 1;
}
istream& operator>>(istream& in, graph& g) {
    int nr_edges, nr_vertices, start, end;
    in >> nr_vertices >> nr_edges;
    g = *(new graph(0,0));
    for (int i = 1; i <= nr_vertices; i++) {
        vertice* v = new vertice(i);
        g.add_vertice(v);
    }
    for (int i = 0; i < nr_edges; i++) {
        in >> start >> end;
        g.add_edge(g.vertices[start], g.vertices[end]);
    }
    return in;
}
istream& operator>>(istream& in, oriented_graph& og) {
    int nr_edges, nr_vertices, start, end;
    in >> nr_vertices >> nr_edges;
    og = *(new oriented_graph(0,0));
    for (int i = 1; i <= nr_vertices; i++) {
        oriented_vertice* v = new oriented_vertice(i);
        og.add_vertice(v);
    }
    for (int i = 0; i < nr_edges; i++) {
        in >> start >> end;
        og.add_edge(og.vertices[start], og.vertices[end]);
    }
    return in;
}
ostream& operator<<(ostream& out, const graph& g) {
    out << g.nr_edges << " " << g.nr_vertices << endl;
    for (int i = 0; i < g.nr_edges; i++) {
        out << g.edges[i]->start->get_id() << " " << g.edges[i]->end->get_id() << endl;
    }
    return out;
}
int main() {
    ifstream fin("sortaret.in");
    oriented_graph g;
    fin >> g;
    g.topo_sort();
    return 0;
}