Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //#include <iostream>
- #include <fstream>
- #include <vector>
- #include <queue>
- #include <set>
- #include <map>
- using namespace std;
- struct Triple {
- int from, to;
- char sym;
- Triple(int from, int to, char sym) :
- from(from), to(to), sym(sym) {}
- };
- const int N = 50001;
- const int M = 26;
- int n, m, k;
- bool isTermin[N];
- int aut[N][M];
- int nums[N];
- int used[N];
- vector<vector<vector<int>>> Inv(N, vector<vector<int>>(M, vector<int>()));
- vector<vector<int>> new_pereh(N, vector<int>(M, -1));
- vector<Triple> min_aut;
- int new_sost_cnt = 0;
- int Class[N];
- void set_used(int v = 1) {
- if (v == 0) return;
- used[v] = true;
- for (int i = 0; i < M; ++i) {
- if (!used[aut[v][i]]) {
- set_used(aut[v][i]);
- }
- }
- }
- void findEquivalenceClasses() {
- set<int> F;
- set<int> NF;
- vector<set<int>> P;
- queue<pair<int, int>> Q;
- for (int i = 0; i < n; ++i) {
- if (isTermin[i]) {
- F.insert(i);
- Class[i] = 0;
- } else {
- NF.insert(i);
- Class[i] = 1;
- }
- }
- P.push_back(F);
- P.push_back(NF);
- for (int i = 0; i < M; ++i) {
- Q.push({0, i});
- Q.push({1, i});
- }
- while (!Q.empty()) {
- auto C = P[Q.front().first];
- auto a = Q.front().second;
- Q.pop();
- map<int, vector<int>> Involved;
- for (auto q : C) {
- for (auto v : Inv[q][a]) {
- Involved[Class[v]].push_back(v);
- }
- }
- for (const auto& p : Involved) {
- if (!p.second.empty()) {
- auto i = p.first;
- if (Involved[i].size() < P[i].size()) {
- int j = P.size();
- P.emplace_back();
- for (auto v : Involved[i]) {
- P[i].erase(v);
- P[j].insert(v);
- }
- if (P[i].size() < P[j].size()) {
- swap(P[i], P[j]);
- }
- for (auto r : P[j]) {
- Class[r] = j;
- }
- for (int z = 0; z < M; ++z) {
- Q.push({j, z});
- }
- }
- }
- }
- }
- }
- void set_min_aut(int v) {
- if (nums[v] == 0) {
- nums[v] = ++new_sost_cnt;
- for (int i = 0; i < M; ++i) {
- if (new_pereh[v][i] != -1) {
- set_min_aut(new_pereh[v][i]);
- min_aut.emplace_back(nums[v], nums[new_pereh[v][i]], i + 'a');
- }
- }
- }
- }
- int main() {
- ifstream cin("minimization.in");
- ofstream cout("minimization.out");
- cin >> n >> m >> k;
- n++;
- int a, b;
- char c;
- for (int i = 0; i < k; ++i) {
- cin >> a;
- isTermin[a] = true;
- }
- for (int i = 0; i < m; ++i) {
- cin >> a >> b >> c;
- aut[a][c - 'a'] = b;
- }
- for (int i = 0; i < n; i++) {
- for (int j = 0; j < M; j++) {
- Inv[aut[i][j]][j].push_back(i);
- }
- }
- set_used();
- findEquivalenceClasses();
- for (int i = 0; i < n; ++i) {
- if (Class[i] != Class[0] && used[i]) {
- for (int j = 0; j < M; ++j) {
- if (Class[aut[i][j]] != Class[0] && used[aut[i][j]]) {
- new_pereh[Class[i]][j] = Class[aut[i][j]];
- }
- }
- }
- }
- set_min_aut(Class[1]);
- set<int> new_isTermin;
- for (int i = 1; i < n; i++) {
- if (isTermin[i] && Class[i] != Class[0] && used[i]) {
- new_isTermin.insert(nums[Class[i]]);
- }
- }
- cout << new_sost_cnt << " " << min_aut.size() << " " << new_isTermin.size() << endl;
- for (int t : new_isTermin) {
- cout << t << " ";
- }
- cout << endl;
- for (auto x : min_aut) {
- cout << x.from << " " << x.to << " " << x.sym << endl;
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement