#include <bits/stdc++.h>
using namespace std;
#define int long long
#define F(i,l,r) for(int i=l,i##_end=r;i<i##_end;i++)
#define all(x) (x).begin(), (x).end()
#define pii pair<int, int>
#define f first
#define s second
template<template<typename> class Container, typename G>
ostream& operator<<(ostream& os, Container<G> x) {int f=0;os<<'{';for(auto&i:x)os<<(f++ ? ", " : ""),os<<i;os<<"}";return os;}
void _print() {cerr << "]\n";}
template<typename T, typename... V>
void _print(T t, V... v) {cerr << t; if (sizeof...(v)) cerr <<", "; _print(v...);}
#ifdef DEBUG
#define dbg(x...) cerr << "\e[91m"<<__func__<<":"<<__LINE__<<" [" << #x << "] = ["; _print(x); cerr << "\e[39m" << endl;
#else
#define dbg(x...)
#endif
int head[2005];
struct edge{int u,nxt;};
edge e[1000005];
int use[1000005],use2[1000005],in[2005],a[1000005],b[1000005];
vector<int>cur;
int32_t main(){
cin.tie(0)->sync_with_stdio(false);
int n,m;cin>>n>>m;
F(i,0,m){
int a,b;cin>>a>>b;
::a[i+1]=a;::b[i+1]=b;
//if(head[a]==0)head[a]=i+1;
//else e[head[a]].nxt=i+1;
e[i+1].u=b;e[i+1].nxt=0;
e[i+1].nxt=head[a];
head[a]=i+1;
}
// let's find a spanning tree
vector<int>seen(n+1);
vector<int>edges;
vector<int>s(n+1),p(n+1),tin(n+1),tout(n+1);int c=0;
int cnt=0;
vector<vector<pii>>above(n+3);
function<void(int)>build=[&](int u){
tin[u]=cnt++;
s[u]=1;
for(int id=head[u];id!=0;id=e[id].nxt){
if(!s[e[id].u] and use[id]==0){
p[e[id].u]=id;
cur.push_back(id);
c++;
use[id]=1;
build(e[id].u);
}
}
tout[u]=cnt++;
};
build(1);
/*F(i,1,m+1){
if(tin[a[i]]<=tin[b[i]] and tout[b[i]]<=tout[a[i]] and use[i]==0){
dbg(b[i],a[i],i);
above[b[i]].emplace_back(a[i],i);
}
}*/
F(i,1,n+1){
for(int id=head[i];id;id=e[id].nxt){
if(tin[i]<=tin[e[id].u] and tout[e[id].u]<=tout[i] and use[id]==0){
above[e[id].u].emplace_back(i,id);
}
}
}
dbg(cur);
function<void(int)>dfs=[&](int u){
if(seen[u])return;
seen[u]=1;
for(int id=head[u];id!=0;id=e[id].nxt){
if(!seen[e[id].u]){
if(use[id]==0){
use[id]=2;
dbg(id);
dfs(e[id].u);
}else if(above[e[id].u].size()){
// these edges could substitute in our tree
int from=above[e[id].u].back().f,ed=above[e[id].u].back().s;
dbg(id,ed,b[ed],b[id],"SWAP");
use[id]=2;use[ed]=1;
above[e[id].u].pop_back();
dfs(e[id].u);
}
}
}
};
dfs(1);
F(i,1,m+1){
dbg(i,use[i]);
if(use[i]==1)edges.push_back(i);
}
dbg(edges);
// build one spanning tree, then let's see if we can build another without using his edges
// when he does an edge and checks if it works, iff its in our tree, we delete that edge, and now we need to find a connection to it that isn't in his tree. If it connects to the converse of our subtree, we win, otherwise we need to like reorient everything?
// we can afford an o(v) query
// eh the data's probably weak and we can do an o(e) update of the tree
vector<int>edges2;seen=vector<int>(n+1);
function<void(int)>dfs2=[&](int u){
if(seen[u])return;
seen[u]=1;
for(int id=head[u];id!=0;id=e[id].nxt){
if(!seen[e[id].u] and use[id]!=1){
edges2.push_back(id);
dfs2(e[id].u);
}
}
};
dfs2(1);
dbg(edges2.size(),edges2);
if(edges.size()==n-1 and edges2.size()==n-1){
F(i,0,n-1)cout<<edges[i]<<" \n"[i==n-2];
F(i,0,n-1)cout<<edges2[i]<<" \n"[i==n-2];
}else{
cout<<"NONE\n";
}
}
| # | Verdict | Execution time | Memory | Grader output |
|---|
| Fetching results... |
| # | Verdict | Execution time | Memory | Grader output |
|---|
| Fetching results... |
| # | Verdict | Execution time | Memory | Grader output |
|---|
| Fetching results... |
| # | Verdict | Execution time | Memory | Grader output |
|---|
| Fetching results... |
| # | Verdict | Execution time | Memory | Grader output |
|---|
| Fetching results... |
| # | Verdict | Execution time | Memory | Grader output |
|---|
| Fetching results... |
| # | Verdict | Execution time | Memory | Grader output |
|---|
| Fetching results... |
| # | Verdict | Execution time | Memory | Grader output |
|---|
| Fetching results... |
| # | Verdict | Execution time | Memory | Grader output |
|---|
| Fetching results... |
| # | Verdict | Execution time | Memory | Grader output |
|---|
| Fetching results... |
| # | Verdict | Execution time | Memory | Grader output |
|---|
| Fetching results... |
| # | Verdict | Execution time | Memory | Grader output |
|---|
| Fetching results... |
| # | Verdict | Execution time | Memory | Grader output |
|---|
| Fetching results... |
| # | Verdict | Execution time | Memory | Grader output |
|---|
| Fetching results... |
| # | Verdict | Execution time | Memory | Grader output |
|---|
| Fetching results... |
| # | Verdict | Execution time | Memory | Grader output |
|---|
| Fetching results... |
| # | Verdict | Execution time | Memory | Grader output |
|---|
| Fetching results... |
| # | Verdict | Execution time | Memory | Grader output |
|---|
| Fetching results... |
| # | Verdict | Execution time | Memory | Grader output |
|---|
| Fetching results... |
| # | Verdict | Execution time | Memory | Grader output |
|---|
| Fetching results... |
| # | Verdict | Execution time | Memory | Grader output |
|---|
| Fetching results... |
| # | Verdict | Execution time | Memory | Grader output |
|---|
| Fetching results... |
| # | Verdict | Execution time | Memory | Grader output |
|---|
| Fetching results... |
| # | Verdict | Execution time | Memory | Grader output |
|---|
| Fetching results... |