#include<bits/stdc++.h>
using namespace std;
#define mx 200005
vector<int>graph[mx];
int visited[mx],start[mx], low[mx];
int timer=1;
stack<int>mystack;
int stack_check[mx];//now all are false
int scc=0;
vector<int>order;
vector<pair<int, int>>backEdge, crossEdge, forwardEdge;
void dfs(int node)
{
visited[node] = 1;
mystack.push(node);
stack_check[node] = 1;
start[node] = timer;
low[node] = timer;
timer++;
for(auto child : graph[node])
{
if(visited[child] == 0)
{
dfs(child);
low[node] = min(low[node], low[child]);
}
else
{
if(stack_check[child] == 1)//it is a back-edge
{
low[node] = min(low[node], start[child]);
backEdge.push_back({node, child});
}
else
{
if(low[node] < low[child]) forwardEdge.push_back({node, child});
else crossEdge.push_back({node, child});
}
//else: it is a cross edge
}
}
stack_check[mystack.top()] = 0;
mystack.pop();
}
int main(){
#ifndef ONLINE_JUDGE
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
#endif
int n,e; cin>>n>>e;
for(int i=1; i<=e; i++)
{
int u,v; cin>>u>>v;
graph[u].push_back(v);
}
for(int i=1; i<=n; i++)
{
if(visited[i] == 0)
{
dfs(i);
}
}
cout<<"Print all back edges: \n";
for(auto it : backEdge)cout<<it.first<<' '<<it.second<<endl;
cout<<"Print all cross edges: \n";
for(auto it : crossEdge)cout<<it.first<<' '<<it.second<<endl;
cout<<"Print all forward edges: \n";
for(auto it : forwardEdge)cout<<it.first<<' '<<it.second<<endl;
cout<<"Print start + minimum start time from n:\n";
for(int i=1; i<=n;i++)
{
cout<<i<<": "<<start[i]<<" - "<<low[i]<<'\n';
}
}
I2luY2x1ZGU8Yml0cy9zdGRjKysuaD4KdXNpbmcgbmFtZXNwYWNlIHN0ZDsKI2RlZmluZSBteCAyMDAwMDUKCnZlY3RvcjxpbnQ+Z3JhcGhbbXhdOwppbnQgdmlzaXRlZFtteF0sc3RhcnRbbXhdLCBsb3dbbXhdOwppbnQgdGltZXI9MTsKc3RhY2s8aW50Pm15c3RhY2s7CmludCBzdGFja19jaGVja1tteF07Ly9ub3cgYWxsIGFyZSBmYWxzZQppbnQgc2NjPTA7CnZlY3RvcjxpbnQ+b3JkZXI7CnZlY3RvcjxwYWlyPGludCwgaW50Pj5iYWNrRWRnZSwgY3Jvc3NFZGdlLCBmb3J3YXJkRWRnZTsKCnZvaWQgZGZzKGludCBub2RlKQp7CiAgIHZpc2l0ZWRbbm9kZV0gPSAxOwogICBteXN0YWNrLnB1c2gobm9kZSk7CiAgIHN0YWNrX2NoZWNrW25vZGVdID0gMTsKICAgc3RhcnRbbm9kZV0gPSB0aW1lcjsKICAgbG93W25vZGVdID0gdGltZXI7CiAgIHRpbWVyKys7CiAgIAogICBmb3IoYXV0byBjaGlsZCA6IGdyYXBoW25vZGVdKQogICB7CiAgICAgIGlmKHZpc2l0ZWRbY2hpbGRdID09IDApCiAgICAgIHsKICAgICAgICAgZGZzKGNoaWxkKTsKICAgICAgICAgbG93W25vZGVdID0gbWluKGxvd1tub2RlXSwgbG93W2NoaWxkXSk7CiAgICAgIH0KICAgICAgZWxzZQogICAgICB7CiAgICAgICAgIGlmKHN0YWNrX2NoZWNrW2NoaWxkXSA9PSAxKS8vaXQgaXMgYSBiYWNrLWVkZ2UKICAgICAgICAgewogICAgICAgICAgICBsb3dbbm9kZV0gPSBtaW4obG93W25vZGVdLCBzdGFydFtjaGlsZF0pOwogICAgICAgICAgICBiYWNrRWRnZS5wdXNoX2JhY2soe25vZGUsIGNoaWxkfSk7CiAgICAgICAgIH0KICAgICAgICAgZWxzZQogICAgICAgICB7CiAgICAgICAgICAgIGlmKGxvd1tub2RlXSA8IGxvd1tjaGlsZF0pIGZvcndhcmRFZGdlLnB1c2hfYmFjayh7bm9kZSwgY2hpbGR9KTsKICAgICAgICAgICAgZWxzZSBjcm9zc0VkZ2UucHVzaF9iYWNrKHtub2RlLCBjaGlsZH0pOwogICAgICAgICB9CiAgICAgICAgIC8vZWxzZTogaXQgaXMgYSBjcm9zcyBlZGdlCiAgICAgIH0KICAgfQogICAKICAgc3RhY2tfY2hlY2tbbXlzdGFjay50b3AoKV0gPSAwOwogICBteXN0YWNrLnBvcCgpOwogICAKfQoKaW50IG1haW4oKXsKI2lmbmRlZiBPTkxJTkVfSlVER0UKICAgZnJlb3BlbigiaW5wdXQudHh0IiwiciIsc3RkaW4pOwogICBmcmVvcGVuKCJvdXRwdXQudHh0IiwidyIsc3Rkb3V0KTsKI2VuZGlmCgogICBpbnQgbixlOyBjaW4+Pm4+PmU7CiAgIGZvcihpbnQgaT0xOyBpPD1lOyBpKyspCiAgIHsKICAgICAgIGludCB1LHY7IGNpbj4+dT4+djsKICAgICAgIGdyYXBoW3VdLnB1c2hfYmFjayh2KTsKICAgfQogICBmb3IoaW50IGk9MTsgaTw9bjsgaSsrKQogICB7CiAgICAgIGlmKHZpc2l0ZWRbaV0gPT0gMCkKICAgICAgewogICAgICAgICBkZnMoaSk7CiAgICAgIH0KICAgfQogICBjb3V0PDwiUHJpbnQgYWxsIGJhY2sgZWRnZXM6IFxuIjsKICAgZm9yKGF1dG8gaXQgOiBiYWNrRWRnZSljb3V0PDxpdC5maXJzdDw8JyAnPDxpdC5zZWNvbmQ8PGVuZGw7CiAgCiAgIGNvdXQ8PCJQcmludCBhbGwgY3Jvc3MgZWRnZXM6IFxuIjsKICAgZm9yKGF1dG8gaXQgOiBjcm9zc0VkZ2UpY291dDw8aXQuZmlyc3Q8PCcgJzw8aXQuc2Vjb25kPDxlbmRsOyAKCiAgIGNvdXQ8PCJQcmludCBhbGwgZm9yd2FyZCBlZGdlczogXG4iOwogICBmb3IoYXV0byBpdCA6IGZvcndhcmRFZGdlKWNvdXQ8PGl0LmZpcnN0PDwnICc8PGl0LnNlY29uZDw8ZW5kbDsgCgogICBjb3V0PDwiUHJpbnQgc3RhcnQgKyBtaW5pbXVtIHN0YXJ0IHRpbWUgZnJvbSBuOlxuIjsKICAgZm9yKGludCBpPTE7IGk8PW47aSsrKQogICB7CiAgICAgIGNvdXQ8PGk8PCI6ICI8PHN0YXJ0W2ldPDwiIC0gIjw8bG93W2ldPDwnXG4nOwogICB9ICAKICAKfQ==