题目:http://codeforces.com/contest/723/problem/F
题意:
给你一个联通无向图
让你构造一个无权生成树,使得——
S点的度数不超过SD
T点的度数不超过TD
分析:
这题和上一题一样都是构造(灵机一动~~)
首先把不包含s和t的边先求一下连通块
处理完后还剩三种边
s-某个连通块 t-某个连通块 s-t
然后对于某个连通块只与s有边,那么连接,t同理
如果某个既可以和s连也可以和t连,那么就分别和s,t连来保持连通
最后连s-t的边
如果到最后图都不连通或者s和t的度不满足,那么无解
否则有解
代码:
#include <bits/stdc++.h>
using namespace std;
const int MAX=4e5+9;
int a[MAX],b[MAX],s,t,ds,dt,n,m,fa[MAX];
bool ms[MAX],mt[MAX];
vector<int> vs,vt;
vector<pair<int,int> > ans;
int findfa(int x){return fa[x]==x?x:fa[x]=findfa(fa[x]);}
void merge(int a,int b) {
if (a==s) ds--;
if (a==t) dt--;
fa[findfa(a)]=findfa(b),ans.push_back(make_pair(a,b));
}
int main() {
ios_base::sync_with_stdio(false),cin.tie(0),cout.tie(0);
cin>>n>>m;
for (int i=1; i<=n; i++) fa[i]=i;
for (int i=1; i<=m; i++) cin>>a[i]>>b[i];
cin>>s>>t>>ds>>dt;
for (int i=1; i<=m; i++)
if (a[i]!=s && a[i]!=t && b[i]!=s && b[i]!=t) {
if (findfa(a[i])!=findfa(b[i]))
merge(a[i],b[i]);
} else {
if (a[i]==s) vs.push_back(b[i]);
if (b[i]==s) vs.push_back(a[i]);
if (a[i]==t) vt.push_back(b[i]);
if (b[i]==t) vt.push_back(a[i]);
}
for (int i=0; i<vs.size(); i++) ms[findfa(vs[i])]=1;
mt[t]=1,ms[s]=1;
for (int i=0; i<vt.size(); i++) {
int x=vt[i];
mt[findfa(x)]=1;
if (!ms[findfa(x)] && findfa(x)!=findfa(t))
merge(x,t),dt--;
}
for (int i=0; i<vs.size(); i++) {
int x=vs[i];
if (!mt[findfa(x)] && findfa(x)!=findfa(s))
merge(x,s),ds--;
}
for (int i=0; i<vs.size(); i++) {
int x=vs[i];
if (findfa(x)!=findfa(s) && findfa(x)!=findfa(t) && ds)
merge(x,s),ds--;
}
for (int i=0; i<vt.size(); i++) {
int x=vt[i];
if (findfa(x)!=findfa(s) && findfa(x)!=findfa(t))
merge(x,t),dt--;
}
for (int i=0; i<vs.size(); i++) {
int x=vs[i];
if (x==t && !dt) ;
else if (findfa(x)!=findfa(s) && ds)
merge(x,s),ds--;
}
for (int i=0; i<vt.size(); i++) {
int x=vt[i];
if (x==s && !ds) ;
else if (findfa(x)!=findfa(t))
merge(x,t),dt--;
}
bool flg=0;
for (int i=2; i<=n; i++) if (findfa(i)!=findfa(1)) flg=1;
if (dt<0 || ds<0 || flg) return cout<<"No\n",0;
cout<<"Yes\n";
for (int i=0; i<ans.size(); i++) cout<<ans[i].first<<" "<<ans[i].second<<'\n';
}