题解:
将除了s, t以外的点相联通的点缩成一个点。
然后将将这些点和分类,
1. 只和s相连, 2 只和t相连 3.同时和s, t相连。
对于1 2来说将他们都连到对应的点上去。
对于3来说,则是能连s就连s, 能连t就连t。
为了保证s, t联通, 我们将第3种点的第一个和s t相连。 (注意处理 s与t直接相连的情况)。
代码:
#include<bits/stdc++.h> using namespace std; #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout); #define LL long long #define ULL unsigned LL #define fi first #define se second #define pb push_back #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define lch(x) tr[x].son[0] #define rch(x) tr[x].son[1] #define max3(a,b,c) max(a,max(b,c)) #define min3(a,b,c) min(a,min(b,c)) typedef pair<int,int> pll; const int inf = 0x3f3f3f3f; const int _inf = 0xc0c0c0c0; const LL INF = 0x3f3f3f3f3f3f3f3f; const LL _INF = 0xc0c0c0c0c0c0c0c0; const LL mod = (int)1e9+7; const int N = 2e5 + 100; int n, m, u, v; int s, t, ds, dt; int pre[N], vis[N]; vector<int> vc[N]; vector<pll> ans; void dfs(int col, int u){ pre[u] = col; vis[u] = 1; for(int v : vc[u]){ if(vis[v]) continue; ans.pb({u, v}); dfs(col, v); } } int cnt[N]; int e[N][2]; int main(){ scanf("%d%d", &n, &m); for(int i = 1; i <= m; ++i){ scanf("%d%d", &u, &v); vc[u].pb(v); vc[v].pb(u); } scanf("%d%d%d%d", &s, &t, &ds, &dt); vis[s] = vis[t] = 1; pre[s] = pre[t] = n + 1; pre[n+1] = n+1; for(int i = 1; i <= n; ++i){ if(vis[i]) continue; dfs(i, i); } for(int v : vc[s]){ cnt[pre[v]] |= 1; e[pre[v]][0] = v; } for(int v : vc[t]){ cnt[pre[v]] |= 2; e[pre[v]][1] = v; } vector<int> zzz; for(int i = 1; i <= n + 1; ++i){ if(i != pre[i]) continue; if(cnt[i] == 1) { ds--; ans.pb({s, e[i][0]}); } if(cnt[i] == 2){ dt--; ans.pb({t, e[i][1]}); } if(cnt[i] == 3) zzz.pb(i); } for(int i = 0; i < zzz.size(); ++i){ v = zzz[i]; if(!i){ ds--, dt--; if(v == n + 1) ans.pb({t, s}); else ans.pb({s, e[v][0]}), ans.pb({t, e[v][1]}); } else { if(v == n+1) continue; if(ds > 0){ ds--; ans.pb({s, e[v][0]}); } else if(dt > 0){ dt--; ans.pb({t, e[v][1]}); } else { puts("No"); return 0; } } } if(ds < 0 || dt < 0){ puts("No"); return 0; } puts("Yes"); for(auto & it : ans){ printf("%d %d\n", it.fi, it.se); } return 0; }