Cod sursa(job #1821610)

Utilizator BrandonChris Luntraru Brandon Data 3 decembrie 2016 13:11:23
Problema Rsir Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.48 kb
#include <fstream>
#include <vector>
#include <algorithm>
#include <cstring>

#define Pe pair <int, int>
#define mp make_pair
#define fi first
#define se second
using namespace std;

ifstream cin ("autobuze3.in");
ofstream cout ("autobuze3.out");

const int MaxN = 200005;

vector <Pe> G[MaxN], Tree[MaxN];
vector <int> Bus[MaxN];
int T, n, m, Cost;
int father[MaxN], depth[MaxN], BusInNode[MaxN];
bool used[MaxN];

class m_edg {
public:
  int nd1, nd2, cost;

  m_edg(int _nd1 = 0, int _nd2 = 0, int _cost = 0) {
    nd1 = _nd1;
    nd2 = _nd2;
    cost = _cost;
  }

  inline bool operator < (const m_edg &other) const {
    return cost < other.cost;
  }
};

vector <m_edg> Edg;

class m_ans {
public:
  string str;
  int a, b, c;

  m_ans(string _str = "", int _a = 0, int _b = 0, int _c = 0) {
    str = _str;
    a = _a;
    b = _b;
    c = _c;
  }
};

vector <m_ans> Ans;

void InitDSU() {
  for (int i = 1; i <= n; ++i) {
    father[i] = i;
    depth[i] = 1;
  }
}

int FindRt(int node) {
  if (father[node] == node) {
    return node;
  }

  return father[node] = FindRt(father[node]);
}

void MergeDSU(int node1, int node2) {
  node1 = FindRt(node1);
  node2 = FindRt(node2);

  if (depth[node1] < depth[node2]) {
    father[node1] = node2;
  }
  else if (depth[node2] < depth[node1]) {
    father[node2] = node1;
  }
  else {
    father[node1] = node2;
    ++depth[node2];
  }
}

void MSP() { ///Minimum Spanning Pom
  sort(Edg.begin(), Edg.end());
  for (auto it: Edg) {
    if (FindRt(it.nd1) == FindRt(it.nd2)) {
      continue;
    }

    MergeDSU(it.nd1, it.nd2);
    Tree[it.nd1].push_back(mp(it.nd2, it.cost));
    Tree[it.nd2].push_back(mp(it.nd1, it.cost));
  }
}

void Dfs(int node = 1, int parent = 0) {
  used[node] = true;
  int MaxBus = node;

  if (Tree[node].size() == 1 and node != 1) {
    return;
  }

  for (auto nxt: Tree[node]) {
    if (used[nxt.fi]) {
      continue;
    }

    Dfs(nxt.fi, node);
    Cost += nxt.se;
    Ans.push_back(m_ans("Drive ", BusInNode[nxt.fi], nxt.fi, node));

    if (Bus[BusInNode[nxt.fi]].size() > Bus[BusInNode[MaxBus]].size()) {
      MaxBus = nxt.fi;
      BusInNode[node] = BusInNode[nxt.fi];
    }
  }

  for (auto nxt: Tree[node]) {
    if (nxt.fi == MaxBus or nxt.fi == parent) {
      continue;
    }

    for (auto it: Bus[BusInNode[nxt.fi]]) {
      Bus[BusInNode[MaxBus]].push_back(it);
      Ans.push_back(m_ans("Move ", it, BusInNode[nxt.fi], BusInNode[MaxBus]));
    }
  }

  if (node != MaxBus) {
    Bus[BusInNode[MaxBus]].push_back(node);
    Ans.push_back(m_ans("Move ", node, node, BusInNode[MaxBus]));
  }
}

inline void ClearTask() {
  Cost = 0;
  memset(used, false, sizeof used);
  for (int i = 1; i <= n; ++i) {
    Tree[i].clear();
    G[i].clear();
    Bus[i].clear();
  }
  Edg.clear();
  Ans.clear();
}

int main() {
  cin >> T;
  for (int task = 1; task <= T; ++task) {
    cin >> n >> m;
    for (int i = 1; i <= m; ++i) {
      int a, b, c;
      cin >> a >> b >> c;
      G[a].push_back(mp(b, c));
      G[b].push_back(mp(a, c));
      Edg.push_back(m_edg(a, b, c));
    }

    InitDSU();
    MSP();

    for (int i = 1; i <= n; ++i) {
      BusInNode[i] = i;
      Bus[i].push_back(i);
    }
    Dfs();

    cout << Cost << '\n';
    for (auto it: Ans) {
      cout << it.str << it.a << ' ' << it.b << ' ' << it.c << '\n';
    }
    cout << "Gata\n";

    ClearTask();
  }
  return 0;
}