Cod sursa(job #3268544)

Utilizator sLinXDinca Robert sLinX Data 15 ianuarie 2025 20:25:29
Problema Arbore partial de cost minim Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 10.46 kb
//  --------------------------------------------------------
// BFS

//#include <iostream>
//#include <fstream>
//
//#include <vector>
//#include <queue>
//
//using namespace std;
//
//
//ifstream f("bfs.in");
//ofstream g("bfs.out");
//vector<vector<int>> lista;
//queue<int> q;
//vector<int> distanta;
//
//int main()
//{
//    int n,m,s;
//    f >> n >> m >> s;
//    int x,y ;
//    lista.resize(n+1);
//    distanta.resize(n+1,-1);
//    q.push(s);
//    distanta[s] = 0;
//    while(f >> x >> y)
//    {
//        lista[x].push_back(y);
//    }
//    while(!q.empty())
//    {
//        int curr = q.front();
//        q.pop();
//        for(auto vecin : lista[curr]){
//            if(distanta[vecin] == -1){
//                distanta[vecin] = distanta[curr] + 1;
//                q.push(vecin);
//            }
//        }
//    }
//
//    for(int i = 1; i<=n ;i++)
//        g << distanta[i] << ' ' ;
//
//    return 0;
//}

// -----------------------------------------------------------------------------
// DFS
//
//#include <iostream>
//#include <fstream>
//#include <vector>
//
//using namespace std;
//
//int n,m;
//
//ifstream f("dfs.in");
//ofstream g("dfs.out");
//
//vector<vector<int>> lista;
//vector<bool> verif;
//
//void dfs(int nod)
//{
//    if(verif[nod])return;
//    verif[nod] = true;
//    for(auto vecin: lista[nod])
//    {
//        dfs(vecin);
//    }
//}
//
//int main()
//{
//    int x,y;
//    f >> n >> m;
//    lista.resize(n+1,{});
//    verif.resize(n+1, false);
//    while(f >> x >> y)
//    {
//        lista[x].push_back(y);
//        lista[y].push_back(x);
//    }
//
//    int nrComp = 0;
//    for(int i = 1; i<=n; i++)
//    {
//        if(!verif[i])
//        {
//            nrComp++;
//            dfs(i);
//        }
//    }
//
//    g << nrComp;
//
//    f.close();
//    g.close();
//
//    return 0;
//}

// ----------------------------------------
// Bipartit

//
//#include <iostream>
//#include <vector>
//#include <queue>
//
//using namespace std;
//
//int n,m;
//vector<vector<int>> lista ;
//vector<int> bipartit;
//queue<int> q;
//
//int main()
//{
//    int x, y;
//    cin >> n >> m;
//    lista.resize(n+1,{});
//    for(int i=1; i<=m ; i++){
//        cin >> x >> y;
//        lista[x].push_back(y);
//        lista[y].push_back(x);
//    }
//    bipartit.resize(n+1, 0);
//    bool turn = true;
//
//    for(int i = 1; i<=n ; i++)
//    {
//        if(bipartit[i] == 0)
//        {
//            turn = true;
//            q.push(i);
//            while(!q.empty())
//            {
//                int size = q.size();
//                while(size)
//                {
//                    int curr = q.front();
//                    q.pop();
//                    if(turn)
//                        bipartit[curr] = 1;
//                    else{
//                        bipartit[curr] = 2;
//                    }
//                    for(auto vec : lista[curr])
//                        if(bipartit[vec] == bipartit[curr])
//                        {
//                            cout << "IMPOSSIBLE";
//                            return 0;
//                        }
//                        else if(bipartit[vec] == 0){
//                            q.push(vec);
//                        }
//                        size--;
//                }
//                turn = !turn;
//
//            }
//        }
//    }
//
//    for (int i = 1; i<=n ;i++)
//        cout << bipartit[i] << ' ';
//
//    return 0;
//}

// --------------------------------------------------------------------------------------
// Sortare topologica
//#include <iostream>
//#include <vector>
//#include <queue>
//using namespace std;
//int n,m;
//vector<vector<int>> lista;
//vector<int> verif;
//vector<int> raspuns;
//vector<int> gradIn;
//queue<int> q;
//
//int main()
//{
//    int x,y;
//    int contor = 0;
//    cin >> n >> m;
//    lista.resize(n+1, {});
//    verif.resize(n+1,0);
//    gradIn.resize(n+1,0);
//    for(int i = 1 ; i<=m ; i++){
//        cin >> x >> y;
//        lista[x].push_back(y);
//        gradIn[y]++;
//    }
//    for(int i = 1 ; i<=n; i++)
//        if(gradIn[i] == 0)
//            q.push(i);
//
//    while (!q.empty())
//    {
//        int curr = q.front();
//        q.pop();
//        raspuns.push_back(curr);
//        verif[curr] = 1;
//        contor++;
//        for(auto vec : lista[curr])
//        {gradIn[vec]--; if (gradIn[vec] == 0)q.push(vec);}
//    }
//    if(contor != n)
//    {
//        cout << "IMPOSSIBLE";
//    }
//    else
//        for(auto el : raspuns)
//            cout << el << ' ';
//
//    return  0;
//}
//// FILL
//#include <iostream>
//#include <vector>
//
//using namespace std;
//
//char mat[1001][1001];
//bool visited[1001][1001];
//int n, m;
//
//int counter;
//
//void fill(int i, int j)
//{
//    if(mat[i][j] != '.')return;
//    if(visited[i][j]) return;
//    if(i<1 || i > n)return;
//    if(j<1 || j >m)return;
//
//    visited[i][j] = true;
//
//    fill(i+1,j);
//    fill(i,j+1);
//    fill(i,j-1);
//    fill(i-1,j);
//}
//
//int main()
//{
//    cin >> n >> m;
//    for(int i = 1; i<= n ; i++)
//    {
//        for(int j = 1; j <= m; j++)
//        {
//            cin >> mat[i][j];
//        }
//    }
//
//    for(int i = 1; i<=n; i++)
//    {
//        for(int j = 1; j<=m ; j++)
//        {
//            if(!visited[i][j] && mat[i][j] == '.')
//            {
//                counter++;
//                fill(i,j);
//            }
//        }
//    }
//
//    cout << counter;
//
//    return 0;
//}
// Tarjan / Submerge
//#include <iostream>
//#include <vector>
//#include <queue>
//#include <cstring>
//using namespace std;
//
//int n, m;
//int x, y;
//int discovery[10005], low[10005], parent[10005];
//int visited[10005];
//int timer = 0;
//
//bool articulation[10005];
//vector<int> lista[10005];
//
//void dfs(int node) {
//    visited[node] = 1;
//    discovery[node] = low[node] = ++timer;
//    int children = 0;
//
//    for (int neighbor : lista[node]) {
//        if (!visited[neighbor]) {
//            children++;
//            parent[neighbor] = node;
//
//            dfs(neighbor);
//
//            low[node] = min(low[node], low[neighbor]);
//
//            // Check if node is an articulation point
//            if (parent[node] == -1 && children > 1) {
//                articulation[node] = true;
//            }
//            if (parent[node] != -1 && low[neighbor] >= discovery[node]) {
//                articulation[node] = true;
//            }
//        } else if (neighbor != parent[node]) {
//            low[node] = min(low[node], discovery[neighbor]);
//        }
//    }
//}
//
//void solveSubmerge() {
//    timer = 0;
//    memset(discovery, 0, sizeof(discovery));
//    memset(low, 0, sizeof(low));
//    memset(parent, -1, sizeof(parent));
//    memset(articulation, false, sizeof(articulation));
//    memset(visited, 0, sizeof(visited));
//
//    for (int i = 1; i <= m; i++) {
//        cin >> x >> y;
//        lista[x].push_back(y);
//        lista[y].push_back(x);
//    }
//
//    // Perform DFS for all nodes to handle disconnected graphs
//    for (int i = 1; i <= n; i++) {
//        if (!visited[i]) {
//            dfs(i);
//        }
//    }
//
//    int answer = 0;
//    for (int i = 1; i <= n; i++) {
//        if (articulation[i]) {
//            answer++;
//        }
//    }
//
//    cout << answer << '\n';
//
//    // Clear graph for next test case
//    for (int i = 1; i <= n; i++) {
//        lista[i].clear();
//    }
//}
//
//int main() {
//    cin >> n >> m;
//    while (n != 0 && m != 0) {
//        solveSubmerge();
//        cin >> n >> m;
//    }
//    return 0;
//}
//// Padure/ Lee
//#include <bits/stdc++.h>
//
//using namespace std;
//
//ifstream fin("padure.in");
//ofstream fout("padure.out");
//
//const int N = 1005;
//int n, m, a[N][N], b[N][N], xs, ys, xf, yf;
//
//pair<int, int> dir[4] = {{0, 1}, {0, -1}, {-1, 0}, {1, 0}};
//deque<pair<int, int>> Q;
//
//bool inmat(int, int);
//void lee(int, int);
//
//int main()
//{
//    fin >> n >> m;
//    fin >> xs >> ys >> xf >> yf;
//    for(int i = 1; i <= n; ++i)
//        for(int j = 1; j <= m; ++j)
//            fin >> a[i][j], b[i][j] = INT_MAX;
//    lee(xs, ys);
//    fout << b[xf][yf];
//    return 0;
//}
//
//bool inmat(int i, int j)
//{
//    return i >= 1 && i <= n && j <= m && j >= 1;
//}
//
//void lee(int xs, int ys)
//{
//    b[xs][ys] = 0;
//    Q.push_front({xs, ys});
//    while(!Q.empty())
//    {
//        int x = Q.front().first;
//        int y = Q.front().second;
//        Q.pop_front();
//        for(int d = 0; d < 4; ++d)
//        {
//            int i = x + dir[d].first;
//            int j = y + dir[d].second;
//            if(inmat(i, j))
//            {
//                int pret = b[x][y] + (a[i][j] != a[x][y] ? 1 : 0);
//                if(pret < b[i][j])
//                {
//                    b[i][j] = pret;
//                    if(!Q.empty() && b[i][j] <= b[Q.front().first][Q.front().second])
//                        Q.push_front({i, j});
//                    else
//                        Q.push_back({i, j});
//                }
//            }
//        }
//    }
//}

// Kruskal
#include <fstream>
#include <iostream>
#include <vector>
#include <queue>
using namespace std;

ifstream f("apm.in");
ofstream g("apm.out");

int n, m;
priority_queue<pair<int, pair<int, int>>> muchii;

int x, y, z;
vector<int> parents;

vector<pair<int, int>> apm;
int cost = 0;

int whoParent(int x) {
    if (parents[x] != x)
        parents[x] = whoParent(parents[x]);  // Path compression
    return parents[x];
}

bool Union(int x, int y) {
    int parentX = whoParent(x);
    int parentY = whoParent(y);

    if (parentX == parentY)  // Already in the same set
        return false;

    parents[parentY] = parentX;  // Union by rank can be added here
    return true;
}

int main() {
    f >> n >> m;

    parents.resize(n + 1);
    for (int i = 1; i <= n; i++)
        parents[i] = i;

    for (int i = 1; i <= m; i++) {
        f >> x >> y >> z;
        muchii.push({-z, {x, y}});  // Cost negativ pentru sortare crescătoare
    }

    while (!muchii.empty()) {
        pair<int, pair<int, int>> curr = muchii.top();
        muchii.pop();

        if (Union(curr.second.first, curr.second.second)) {
            cost += -curr.first;  // Reversăm semnul pentru costul real
            apm.push_back(curr.second);
        }

        if (apm.size() == n - 1)  // Gata când avem n-1 muchii
            break;
    }

    g << cost << '\n';
    g << apm.size() << '\n';
    for (auto elem : apm) {
        g << elem.first << ' ' << elem.second << '\n';
    }

    return 0;
}