Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- */
- //#pragma comment(linker, "/STACK:16777216")
- #define _CRT_SECURE_NO_WARNINGS
- #include <fstream>
- #include <iostream>
- #include <string>
- #include <complex>
- #include <math.h>
- #include <set>
- #include <vector>
- #include <map>
- #include <queue>
- #include <stdio.h>
- #include <stack>
- #include <algorithm>
- #include <list>
- #include <ctime>
- #include <memory.h>
- #include <assert.h>
- #define y0 sdkfaslhagaklsldk
- #define y1 aasdfasdfasdf
- #define yn askfhwqriuperikldjk
- #define j1 assdgsdgasghsf
- #define tm sdfjahlfasfh
- #define lr asgasgash
- #define norm asdfasdgasdgsd
- #define eps 1e-9
- #define M_PI 3.141592653589793
- #define bs 1000000007ll
- #define bsize 350
- using namespace std;
- const int INF = 1e9;
- const int N = 550000;
- int n, m;
- int a, b;
- vector<int> g[N];
- int used[N];
- int par[N];
- int cycle_start;
- int cycle_end;
- int dfs(int v)
- {
- //cout << v << "%!" << par[v] << endl;
- used[v] = 1;
- for (int i = 0; i < g[v].size(); i++)
- {
- int to = g[v][i];
- if (used[to] == 2)
- continue;
- if (used[to] == 0)
- {
- par[to] = v;
- //cout << "!!!" << v << " " << to << endl;
- if (dfs(to))
- return true;
- }
- else
- {
- cycle_end = v;
- cycle_start = to;
- return true;
- }
- }
- used[v] = 2;
- return false;
- }
- vector<int> get_cycle()
- {
- int cur = cycle_end;
- vector<int> res;
- res.push_back(cur);
- while (true)
- {
- //cout << cur << endl;
- //cin.get();
- cur = par[cur];
- res.push_back(cur);
- if (cur == cycle_start)
- break;
- }
- reverse(res.begin(), res.end());
- return res;
- }
- int on_cycle[N];
- int block_L, block_R;
- int T;
- set<int>::iterator it;
- set<int> bad_vertices;
- vector<pair<int, int> > good_edges;
- void add_edge(int a, int b)
- {
- good_edges.push_back(make_pair(a, b));
- }
- vector<int> V;
- void run_magic_checker(int id) // either id-th vertex of cycle or no vertices at all
- {
- for (int i = 1; i <= n; i++)
- {
- used[i] = 0;
- }
- used[V[id]] = 2;
- cycle_start = 0;
- cycle_end = 0;
- for (int i = 1; i <= n; i++)
- {
- if (used[i])
- continue;
- if (dfs(i))
- break;
- }
- if (cycle_start != 0)
- {
- cout << 0 << endl;
- cout << endl;
- }
- else
- {
- cout << 1 << endl;
- cout << V[id] << endl;
- }
- }
- pair<int, int> DP[N];
- bool larger(int a, int b)
- {
- if (b >= block_L)
- {
- if (a > b)
- return true;
- if (a < block_L)
- return true;
- return false;
- }
- return (a>b&&a < block_L);
- }
- pair<int, int> update(pair<int, int> P, int to)
- {
- to = on_cycle[to] - 1;
- if (larger(P.first, to) || P.first == 1000000000)
- P.first = to;
- if (larger(to, P.second) || P.second == -1000000000)
- P.second = to;
- return P;
- }
- pair<int, int> combine(pair<int, int> P1, pair<int, int> P2)
- {
- if (larger(P1.first, P2.first) || P1.first == 1000000000)
- P1.first = P2.first;
- if (P2.second>=0&&(larger(P2.second, P1.second) || P1.second == -1000000000))
- P1.second = P2.second;
- return P1;
- }
- bool is_next(int a, int b)
- {
- int Q = on_cycle[b];
- Q++;
- if (Q > V.size())
- Q = 1;
- return (Q == on_cycle[a]);
- }
- pair<int, int> magic_dfs(int v)
- {
- //cout << v << "^!" << on_cycle[v] << endl;
- if (used[v] == T)
- return DP[v];
- if (used[v] <= T - 2&&used[v]!=0)
- {
- DP[v] = make_pair(1000000000, -1000000000);
- return DP[v];
- }
- if (used[v] == 0)
- used[v] = T;
- else
- used[v] = -100500;
- DP[v] = make_pair(1000000000, -1000000000);
- for (int i = 0; i < g[v].size(); i++)
- {
- int to = g[v][i];
- if (on_cycle[v] && on_cycle[to] && (is_next(to, v)))
- continue;
- //cout << v << "%" << to << " " << on_cycle[to] << endl;
- if (on_cycle[to])
- {
- DP[v] = update(DP[v], to);
- continue;
- }
- DP[v] = combine(DP[v], magic_dfs(to));
- }
- // cout << v << "%" << DP[v].first << "%" << DP[v].second << endl;
- return DP[v];
- }
- int Rand()
- {
- int res = 0;
- for (int i = 0; i<= 60; i++)
- {
- res = res * 2 + rand() % 2;
- if (res >= n)
- res -= n;
- }
- return res;
- }
- int main(){
- //freopen("fabro.in","r",stdin);
- //freopen("fabro.out","w",stdout);
- //freopen("F:/input.txt", "r", stdin);
- //freopen("F:/output.txt", "w", stdout);
- ios_base::sync_with_stdio(0);
- //cin.tie(0);
- // freopen("input.txt", "r", stdin);
- cin >> n >> m;
- for (int i = 1; i <= m; i++)
- {
- //cout << i << endl;
- cin >> a >> b;
- /* a = Rand() + 1;
- b = Rand() + 1;
- while (b == a)
- {
- b = b + 1;
- if (b > n)
- b = 1;
- }
- */
- g[a].push_back(b);
- }
- // cout << "E" << endl;
- for (int i = 1; i <= n; i++)
- {
- if (used[i])
- continue;
- if (dfs(i))
- break;
- }
- // cout << "@" << endl;
- /*for (int i = 1; i <= n; i++)
- {
- cout << i << "%" << par[i] << endl;
- }*/
- //cout << "@" << endl;
- //cout << cycle_start << " " << cycle_end << " " <<endl;
- if (cycle_start == 0)// dag
- {
- cout << "NIE" << endl;
- return 0;
- }
- V = get_cycle();
- for (int i = 1; i <= n; i++)
- used[i] = 0;
- for (int i = 0; i < V.size(); i++)
- {
- int v = V[i];
- used[v] = 2;
- }
- cycle_start = 0;
- cycle_end = 0;
- for (int i = 1; i <= n; i++)
- {
- if (used[i])
- continue;
- if (dfs(i))
- break;
- }
- if (cycle_start != 0) // still have a cycle
- {
- cout << 0 << endl;
- cout << endl;
- return 0;
- }
- /*
- for (int i = 0; i < V.size(); i++)
- {
- cout << V[i] << " ";
- }
- cout << endl;
- */
- for (int i = 0; i < V.size(); i++)
- {
- on_cycle[V[i]] = i + 1;
- }
- int covered_L = 0;
- block_L = block_R = 0;
- int Done = 0;
- for (int i = 1; i <= n; i++)
- {
- used[i] = 0;
- }
- while (true)
- {
- ++T;
- //cout << block_L << " " << block_R << endl;
- int new_max = block_R;
- // cout << block_L << " %" << block_R << endl;
- /*for (int i = 1; i <= 3; i++)
- {
- cout << DP[i].first << "%" << DP[i].second << endl;
- }
- */
- /* for (int i = 1; i <= n; i++)
- {
- cout << DP[i].first << " " << DP[i].second << " " << i << " "<<used[i]<<endl;
- }
- cout << endl;
- */
- for (int i = block_L; i <= block_R; i++)
- {
- ++Done;
- pair<int, int> Q = magic_dfs(V[i]);
- // max ovr this base, min ovr this base, use only vertices from last iteration + unused
- // cout << "@" <<i<<"^"<< Q.first << "^" << Q.second <<" "<<block_L<<" "<<block_R<< endl;
- // cout << DP[2].first << "%%" << DP[2].second << endl;
- // cout << DP[4].first << "%" << DP[4].second << endl;
- if (Q.second < 0)
- continue;
- if (larger(Q.second, new_max))
- new_max = Q.second;
- add_edge(i, Q.first);
- add_edge(i, Q.second);
- //cout << Q.first<< "%" << Q.second << endl;
- //cin.get();
- if (Q.first <= i) // within block, <=1 fixed vertices; maybe this one
- {
- continue;
- run_magic_checker(i);
- return 0;
- }
- }
- // cout << block_L << " " << block_R << " " << new_max << endl;
- // cin.get();
- block_L = block_R + 1;
- block_R = max(new_max, block_R + 1);
- if (block_L >= V.size())
- block_L = 0;
- if (block_R >= V.size())
- block_R = 0;
- if (Done > V.size())
- break;
- }
- for (int i = 0; i < V.size(); i++)
- {
- bad_vertices.insert(i);
- }
- for (int i = 0; i < good_edges.size(); i++)
- {
- int v1 = good_edges[i].first;
- int v2 = good_edges[i].second;
- //cout << "!!" << v1 << " " << v2 << endl;
- if (v1 == v2)
- {
- int flag = 0;
- if (bad_vertices.find(v1) != bad_vertices.end())
- {
- flag = 1;
- }
- bad_vertices.clear();
- if (flag)
- bad_vertices.insert(v1);
- }
- if (v1 < v2)
- {
- while (true)
- {
- it = bad_vertices.upper_bound(v1);
- if (it == bad_vertices.end())
- break;
- int val = (*it);
- if (val >= v2)
- {
- break;
- }
- bad_vertices.erase(val);
- }
- }
- else // over cycle start
- {
- while (true)
- {
- it = bad_vertices.upper_bound(v1);
- if (it == bad_vertices.end())
- break;
- int val = (*it);
- bad_vertices.erase(val);
- }
- while (true)
- {
- it = bad_vertices.begin();
- if (it == bad_vertices.end())
- break;
- int val = (*it);
- if (val >= v2)
- break;
- bad_vertices.erase(val);
- }
- }
- }
- vector<int> ans;
- for (it = bad_vertices.begin(); it != bad_vertices.end(); it++)
- {
- int val = (*it);
- ans.push_back(V[val]);
- }
- sort(ans.begin(), ans.end());
- cout << ans.size() << endl;
- for (int i = 0; i < ans.size(); i++)
- {
- if (i)
- cout << " ";
- cout << ans[i];
- }
- cout << endl;
- cin.get(); cin.get();
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement