首先可以发现由于图是无环的,所以原问题 ⇔ \Leftrightarrow ⇔选 2 ∗ ( n − 1 ) 2*(n-1) 2∗(n−1)条边其中满足这个边集的诱导子图除了 a a a的每一个点都有 1 1 1的入度,每一个除了 b b b的点有 1 1 1的出度。
然后就可以很轻松转换成网络流的题。时间复杂度 O ( n + m ∗ n ) O(n+m*\sqrt n) O(n+m∗n)会TLE。
但是由于一个边只配两个点,所以可以构造基环数。时间复杂度 O ( n + m ) O(n+m) O(n+m)
Code:
/*
{By GWj
*/
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define rb(a,b,c) for(int a=b;a<=c;++a)
#define rl(a,b,c) for(int a=b;a>=c;--a)
#define LL long long
#define IT iterator
#define PB push_back
#define II(a,b) make_pair(a,b)
#define FIR first
#define SEC second
#define FREO freopen("check.out","w",stdout)
#define rep(a,b) for(int a=0;a<b;++a)
#define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define random(a) rng()%a
#define ALL(a) a.begin(),a.end()
#define POB pop_back
#define ff fflush(stdout)
#define fastio ios::sync_with_stdio(false)
#define R(a) cin>>a
#define R2(a,b) cin>>a>>b
#define check_min(a,b) a=min(a,b)
#define check_max(a,b) a=max(a,b)
using namespace std;
const int INF=0x3f3f3f3f;
typedef pair<int,int> mp;
/*}
*/
vector<int> g[1000000+1],id[1000000+1];
int n,m,a,b;
int siz[1000000+1];
bool spe[1000000+1];
struct DSU{
int fa[1000000+1],inc[1000000+1];
void init(int N){
rb(i,1,N)
fa[i]=i,inc[i]=1;
}
int root(int N){
if(fa[N]==N) return N;
return fa[N]=root(fa[N]);
}
void merge(int u,int v){
inc[root(v)]+=inc[root(u)];
fa[root(u)]=root(v);
}
}dsu;
int rest[1000000+1];
bool vis[1000000+1];
void work1(int root){
vis[root]=1;
rep(i,g[root].size()){
int it=g[root][i];
if(!vis[it]){
if(it>n/2)
rest[id[root][i]]=1;
else
rest[id[root][i]]=2;
work1(it);
}
}
}
int zz=0;
bool find_cycle;
bool work(int root,int pre){
vis[root]=1;
bool okk=0;
rep(i,g[root].size()){
int it=g[root][i];
if(it==pre){
pre=-1;
continue;
}
if(vis[it]){
if(find_cycle) continue;
find_cycle=1;
zz=it;
rest[id[root][i]]=(zz>n/2? 1:2);
}
else{
if(work(it,root)) {
okk=1;
rest[id[root][i]]=(root>n/2? 1:2);
}
else{
rest[id[root][i]]=(it>n/2? 1:2);
}
}
}
if(root==zz) okk=1;
return okk;
}
void mian(){
n<<=1;
rb(i,1,n)
g[i].clear(),id[i].clear();
dsu.init(n);
rb(i,1,n)
siz[i]=0,vis[i]=0;
vector<mp> edges;
rb(i,1,m){
rest[i]=0;
int u,v;
R2(u,v);
edges.PB(II(u,v));
dsu.merge(u,v+n/2);
id[u].PB(i);
id[v+n/2].PB(i);
g[u].PB(v+n/2);
g[v+n/2].PB(u);
}
for(mp edg:edges){
siz[dsu.root(edg.FIR)]++;
}
spe[dsu.root(a+n/2)]=1;
spe[dsu.root(b)]=1;
bool ok=1;
rb(i,1,n){
if(dsu.root(i)==i){
if(!spe[i]&&dsu.inc[i]==siz[i]+1){
ok=0;
}
}
}
cout<<(ok? "YES":"NO")<<endl;
if(ok){
work1(dsu.root(a+n/2));
if(dsu.root(a+n/2)!=dsu.root(b)){
work1(dsu.root(b));
}
rb(i,1,n)
if(!spe[i]&&dsu.root(i)==i)
zz=0,find_cycle=0,work(i,0);
vector<int> res1,res2;
rb(i,1,m)
if(rest[i])
if(rest[i]==1) res1.PB(i);
else res2.PB(i);
for(auto it:res1) cout<<it<<" ";cout<<endl;
for(auto it:res2) cout<<it<<" ";cout<<endl;
}
spe[dsu.root(a+n/2)]=0;
spe[dsu.root(b)]=0;
}
int main(){
fastio;
while(cin>>n>>m>>a>>b){
mian();
}
return 0;
}