// compile: make data
// run: ./data < data.in
#include <bits/stdc++.h>
using namespace std;
#pragma GCC optimize("O3,unroll-loops")
#pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt")
#ifdef LOCAL
#include <debug/codeforces.h>
#define debug(x...) _debug_print(#x, x);
#define Debug(x...) _debug_print_format(#x, x);
#else
#define debug(x...)
#define Debug(x...)
#endif
template<typename...Args> void print_(Args...args){((cout<<args<<" "),...)<<endl;}
typedef std::vector<int> VI;
typedef std::vector<std::vector<int>> VII;
typedef std::vector<std::vector<std::vector<int>>> VIII;
#define rep(i,a,b) for(int i=(a);i<(int)(b);++i)
#define sz(v) ((int)(v).size())
#define print(...) print_(__VA_ARGS__);
#define FIND(a, x) ((find(a.begin(),a.end(),(x))!=a.end())?1:0)
#define cmin(x,...) x=min({(x), __VA_ARGS__})
#define cmax(x,...) x=max({(x), __VA_ARGS__})
#define INTMAX (int)(9223372036854775807)
#define INF (int)(1152921504606846976)
#define double long double
#define int long long
#define MAXN 200010
struct graph {
struct node {
int v, w;
bool operator<(const node &other) const {
return w < other.w;
}
bool operator==(const node &other) const {
return v == other.v && w == other.w;
}
};
vector<vector<node>> e;
int n;
bool directed;
graph(int V, bool D = 0) {
n = V;
e.resize(n);
directed = D;
}
void add_edge(int u, int v, int w = 1) {
e[u].push_back(node{v, w});
}
void tarjan_scc(vector<vector<int>> &scc, vector<int> &belong) {
stack<int> s;
vector<int> dfn(n), low(n), instack(n);
int dfncnt;
scc.clear(), belong.resize(n, -1);
function<void(int)> dfs = [&](int u) {
low[u] = dfn[u] = ++dfncnt, s.push(u), instack[u] = 1;
for (auto edge: e[u]) {
int v = edge.v;
if (!dfn[v]) dfs(v), cmin(low[u], low[v]);
else if (instack[v]) cmin(low[u], dfn[v]);
}
if (dfn[u] == low[u]) {
scc.push_back(vector<int>{});
while (s.top() != u) {
belong[s.top()] = sz(scc) - 1;
scc.back().push_back(s.top());
instack[s.top()] = 0, s.pop();
}
belong[s.top()] = sz(scc) - 1;
scc.back().push_back(s.top());
instack[s.top()] = 0, s.pop();
}
};
rep(i, 0, n) if (!~belong[i]) dfs(i);
}
void graphviz_dump(string filename = "graph.dot") {
ofstream gf; gf.open(filename);
gf << (directed ? "digraph" : "graph") << " {\n";
gf << " "; rep(i, 0, n) gf << i << " ;"[i==n-1]; gf << endl;
string notation = directed ? " -> " : " -- ";
bool weighted = 0;
for (auto es: e) for (auto edge: es) if (edge.w != 1) weighted = 1;
rep(u, 0, n) {
for (auto [v, w]: e[u]) {
if (!directed && u > v) continue;
gf << " " << u << notation << v << (weighted ? " ;\n" : ";\n");
}
}
gf << "}\n";
}
};
int32_t main() {
ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
int n, m; cin >> n >> m;
graph g(n, 1);
rep(i, 0, m) {
int u, v; cin >> u >> v; --u, --v;
g.add_edge(u, v);
}
g.graphviz_dump();
vector<vector<int>> scc;
vector<int> belong;
g.tarjan_scc(scc, belong);
if (sz(scc) == 1) {
cout << "YES" << endl;
return 0;
}
cout << "NO" << endl;
int U = scc[0][0], V = scc[1][0];
vector<int> vis(n, 0);
function<void(int)> dfs = [&](int u) {
vis[u] = 1;
for (auto edge: g.e[u]) {
int v = edge.v;
if (vis[v]) continue;
dfs(v);
}
};
if (vis[V]) cout << V+1 << " " << U+1 << endl;
else cout << U+1 << " " << V+1 << endl;
return 0;
}
Hey, heard about CF Gold Rush. Is anyone participating? Seems like a fun competition with a nice prize. Share what you think. cfgoldrush
For my Brazilian friends, 1bbetbr.com is pretty sweet. They have all the local sports and games I am into. I am hoping to win some serious dough! Check it out at 1bbetbr!
Leon89? I’m cautiously optimistic. The aesthetic looks good, and they’ve got what I’m looking for. Time will tell, but it seems on the up and up. For sure a place to watch! leon89
Alright fam, 66biolink is where it’s at for quick links. So easy to use and lets you organize everything like a pro. Def recommend it. Check out 66biolink.
What up! 9777game looking kinda tempting, gonna throw some coins their way, wish me luck! Check it out here 9777game
New to 8777cx. Looks promising! Anything I should know before diving in? Is there a good community around it. Jump into 8777cx