Cod sursa(job #2808080)

Utilizator DananauStefanRazvanDananau Stefan-Razvan DananauStefanRazvan Data 24 noiembrie 2021 16:03:44
Problema Diametrul unui arbore Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 11.06 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <stack>
#include <list>
#include <utility>
#include <set>
#include <algorithm>
#include <bits/stdc++.h>

using namespace std;

#define INF 0x3f3f3f3f

class Graph {
    protected:
        int n;
        int m;
        vector<vector<int>> adjList;
        vector<bool> vis;
        vector<int> dist;
    public:
        Graph() {};
        void royFloyd();
};

class UndirectedGraph : public Graph {
    private:
        int noCompConex;
    public:
        UndirectedGraph(string inPath);
        void dfs(int start);
        int dfsCompConex(string outPath);
};

UndirectedGraph :: UndirectedGraph(string inPath) {
    ifstream in(inPath);

    int n, m;

    in >> n >> m;

    this -> n = n;
    this -> m = m;
    adjList.resize(n + 1);
    vis.resize(n + 1);

    for (int i = 0; i < m; i++) {
        int x, y;
        in >> x >> y;
        adjList[x].push_back(y);
        adjList[y].push_back(x);
    }
}

void UndirectedGraph :: dfs(int start) {
    vis[start] = true;

    for (auto x : adjList[start])
        if (!vis[x])
            dfs(x);
}

int UndirectedGraph :: dfsCompConex(string outPath) {
    ofstream out(outPath);

    noCompConex = 0;

    for (int i = 1; i <= n; i++)
        if (!vis[i]) {
            dfs(i);
            noCompConex++;
        }

    out << noCompConex;

    return noCompConex;
}

class DirectedGraph : public Graph {
    private:
        stack<int> topSorted;
    public:
        DirectedGraph(string inPath);
        void bfs(int start);
        vector<int> getBfs(string outPath);
        void dfsTopSort(int start);
        void topSort(string outPath);
};

DirectedGraph :: DirectedGraph(string inPath) {
    ifstream in(inPath);

    int n, m;

    in >> n >> m;

    this -> n = n;
    this -> m = m;
    adjList.resize(n + 1);
    vis.resize(n + 1);
    dist.resize(n + 1, -1);

    for (int i = 0; i < m; i++) {
        int x, y;
        in >> x >> y;
        adjList[x].push_back(y);
    }
}

void DirectedGraph :: bfs(int start) {
    queue<int> q;

    dist[start] = 0;
    q.push(start);

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

        for (auto i : adjList[node])
            if (dist[i] == -1) {
                dist[i] = dist[node] + 1;
                q.push(i);
            }
    }
}

vector<int> DirectedGraph :: getBfs(string outPath) {
    ofstream out(outPath);

    for (int i = 1; i <= n; i++)
        out << dist[i] << " ";

    return dist;
}

void DirectedGraph :: dfsTopSort(int start) {
    vis[start] = true;

    for (auto x : adjList[start])
        if (!vis[x])
            dfsTopSort(x);

    topSorted.push(start);
}

void DirectedGraph :: topSort(string outPath) {
    ofstream out(outPath);

    for (int i = 1; i <= n; i++)
        if (!vis[i])
            dfsTopSort(i);

    while (!topSorted.empty()) {
        out << topSorted.top() << " ";
        topSorted.pop();
    }
}

class UndirectedWeightedGraph : public Graph {
    private:
        struct edge {
            int a, b;
            int w;
            friend bool operator<(const edge& A, const edge& B) {
                return A.w < B.w;
            }
        };
        vector<edge> adjList;
        vector<int> subset;
        vector<pair<int, int>> sol;
        int partialCost = 0;
    public:
        UndirectedWeightedGraph(string inPath);
        int findNode(int node);
        void unite(int node1, int node2);
        void kruskal();
        vector<pair<int, int>> apm(string outPath);
        void disjoint(string intPath, string outPath);
};

UndirectedWeightedGraph :: UndirectedWeightedGraph(string inPath) {
    ifstream in(inPath);

    int n, m;

    in >> n >> m;

    this -> n = n;
    this -> m = m;
    subset.resize(n + 1);

    for (int i = 1; i <= n; i++)
        subset[i] = i;

    for (int i = 1; i <= m; i++) {
        edge X;
        in >> X.a >> X.b >> X.w;
        adjList.push_back(X);
    }
}

int UndirectedWeightedGraph :: findNode(int node) {
    if (node == subset[node])
        return node;

    return subset[node] = findNode(subset[node]);
};

void UndirectedWeightedGraph :: unite(int node1, int node2) {
    int a = findNode(node1);
    int b = findNode(node2);
    subset[b] = a;
}

void UndirectedWeightedGraph :: kruskal() {
    sort(adjList.begin(), adjList.end());

    for (auto i : adjList) {
        int a = findNode(i.a);
        int b = findNode(i.b);

        if (a == b)
            continue;
        else {
            unite(i.a, i.b);
            sol.emplace_back(i.a, i.b);
            partialCost += i.w;
        }
    }
}

vector<pair<int, int>> UndirectedWeightedGraph :: apm(string outPath) {
    ofstream out(outPath);

    out << partialCost << '\n' << n - 1 << '\n';
    for (auto i : sol)
        out << i.first << " " << i.second << '\n';

    return sol;
}

void UndirectedWeightedGraph :: disjoint(string inPath, string outPath) {
    ifstream in(inPath);
    ofstream out(outPath);

    int n, m;

    in >> n >> m;

    while (m) {
        int c, x, y;

        in >> c >> x >> y;

        if (c == 1)
            unite(x, y);
        else
            if (findNode(x) == findNode(y))
                out << "DA\n";
            else
                out << "NU\n";
        m--;
    }
}

class DirectedWeightedGraph : public Graph {
    private:
        vector<vector<pair<int, int>>> adjList;
        priority_queue <pair<int, int>> q;
        vector<int> used;
        bool finish = false;
    public:
        DirectedWeightedGraph(string inPath);
        void dijkstra(int start);
        vector<int> dijkstraDist(int start, string outPath);
        void bellmanford(int start);
        vector<int> bellmanfordDist(int start, string outpath);
};

DirectedWeightedGraph :: DirectedWeightedGraph(string inPath) {
    ifstream in(inPath);

    int n, m;

    in >> n >> m;

    this -> n = n;
    this -> m = m;
    adjList.resize(n + 1);
    dist.resize(n + 1, INF);
    used.resize(n + 1);
    vis.resize(n + 1);

    for (int i = 0; i < m; i++) {
        int x, y, w;
        in >> x >> y >> w;
        adjList[x].push_back(make_pair(y, w));
    }
}

void DirectedWeightedGraph :: dijkstra(int start) {
    dist[start] = 0;
    q.push(make_pair(0, start));

    while (!q.empty()) {
        int node = q.top().second;

        if (dist[node] != q.top().first) {
            q.pop();
            continue;
        }

        q.pop();

        for (auto x : adjList[node])
            if (dist[node] + x.second < dist[x.first]) {
                dist[x.first] = dist[node] + x.second;
                q.push(make_pair(dist[x.first], x.first));
            }
    }
}

vector<int> DirectedWeightedGraph :: dijkstraDist(int start, string outPath) {
    ofstream out(outPath);

    for (int i = 1; i <= n; i++)
        if (dist[i] != INF)
            out << dist[i] << " ";
        else
            out << 0 << " ";

    return dist;
}
void DirectedWeightedGraph :: bellmanford(int start) {
    queue<int> q;

    dist[start] = 0;
    q.push(start);

    while (!q.empty()) {
        if (finish)
            break;

        int x = q.front();
        q.pop();
        vis[x] = false;

        for (auto i : adjList[x])
            if (dist[i.first] > dist[x] + i.second) {
                used[i.first]++;

                if (used[i.first]  == n) {
                    finish = true;
                    break;
                }

                dist[i.first] = dist[x] + i.second;

                if (vis[i.first] == false) {
                    q.push(i.first);
                    vis[i.first] = true;
                }
            }
    }
}

vector<int> DirectedWeightedGraph :: bellmanfordDist(int start, string outPath) {
    ofstream out(outPath);

    if (finish)
        out << "Ciclu negativ!";

    for (int i = 1; i <= n; i++)
        out << dist[i] << " ";

    return dist;
}

class Tree : public Graph {
    private:
        int diam;
        int last;
    public:
        Tree(string inPath);
        void bfsDarb(int start);
        int distDarb(int start, string outPath);
};

Tree :: Tree(string inPath) {
    ifstream in(inPath);

    int n;

    in >> n;

    this -> n = n;
    adjList.resize(n + 1);
    dist.resize(n + 1);

    for (int i = 1; i < n; i++) {
        int x, y;
        in >> x >> y;
        adjList[x].push_back(y);
        adjList[y].push_back(x);
    }
}

void Tree :: bfsDarb(int start) {
    queue<int> q;
    dist[start] = 1;
    q.push(start);

    while (!q.empty()) {
        int x = q.front();
        last = x;

        for (auto y : adjList[x]) {
            if (!dist[y]) {
                dist[y] = dist[x] + 1;
                q.push(y);
            }
        }

        q.pop();
    }

    diam = dist[last];

}

int Tree :: distDarb(int start, string outPath) {
    ofstream out(outPath);

    bfsDarb(start);
    dist.assign(n + 1, 0);
    bfsDarb(last);

    out << diam;

    return diam;
}
///////////////////////////////

void Graph :: royFloyd() {
    ifstream fin("royfloyd.in");
    ofstream fout("royfloyd.out");

    int n;

    fin >> n;

    adjList.resize(n + 1, vector<int> (n + 1, 0));

    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++) {
            fin >> adjList[i][j];
            if (adjList[i][j] == 0 && i != j)
                adjList[i][j] = INF;
        }

    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            for (int k = 0; k < n; k++)
                if (adjList[j][i] + adjList[i][k] < adjList[j][k])
                    adjList[j][k] = adjList[j][i] + adjList[i][k];

    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++)
            fout << adjList[i][j] << " ";
        fout << '\n';
    }
}

int main()
{
    /* dfs O(n + m)
    UndirectedGraph X = UndirectedGraph("dfs.in");
    X.dfsCompConex("dfs.out");
    */

    /* bfs O(n + m)
    DirectedGraph X = DirectedGraph("bfs.in");
    X.bfs(2);
    X.getBfs("bfs.out");
    */

    /* Top Sort O(n + m)
    DirectedGraph X = DirectedGraph("sortaret.in");
    X.topSort("sortaret.out");
    */

    /* apm O(m*logn + m*logm)
    UndirectedWeightedGraph X = UndirectedWeightedGraph("apm.in");
    X.kruskal();
    X.apm("apm.out");
    */

    /* disjoint O(m)
    UndirectedWeightedGraph X("disjoint.in");
    X.disjoint("disjoint.in", "disjoint.out");
    */

    /* dijkstra O(m*logn)
    DirectedWeightedGraph X = DirectedWeightedGraph("dijkstra.in");
    X.dijkstra(1);
    X.dijkstraDist(1, "dijkstra.out");
    */

    /* bellman ford O(n*m)
    DirectedWeightedGraph X = DirectedWeightedGraph("bellmanford.in");
    X.bellmanford(1);
    X.bellmanfordDist(1, "bellmanford.out");
    */

    Tree X = Tree("darb.in");
    X.distDarb(1, "darb.out");
    return 0;
}