大体题意:
给你一个无向图,要求构造出一个生成树来,使得s,t 的度数不超过ds 和dt,多解任意输出!
思路:
很好的一道题目,请教了学长!
先把s和t结点去掉,构造出多个连通块来,然后依次于s和t 相连!
既能连s又能连t的联通块是比较好的,最后在处理,先把那些只能连接一个节点的联通快先连起来,并且计数统计!
然后在根据当前的计数来加那些万能联通块。
注意:
细节比较多,说几个方面:
1. 某个联通块是万能的 不是存在一个节点既能连s和t,而是存在1个以上就行,就是第一个连s,第二个连t!
2. 仔细处理万能连通块。
3. 还需要判断s和t 需不需要直接相连!
代码写的很乱 参考以下吧:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 400000 + 10;
struct Node{
int u,v;
void read(){
scanf("%d %d",&u, &v);
}
}p[maxn];
int fa[maxn];
set<int>g[2];
set<int>bing[maxn>>1];
set<int>::iterator it;
vector<pair<int,int> > ans;
vector<pair<int,int> > Do;
int find(int x){
return fa[x] == x ? fa[x] : fa[x] = find(fa[x]);
}
void add(int x,int y){
int xx = find(x);
int yy = find(y);
if (xx != yy){
if (xx > yy)swap(xx,yy);
fa[yy] = xx;
}
}
int n,m;
int s,t,ds,dt;
bool ok(){
for (int i = 0; i <= n; ++i)fa[i] = i;
for (int i = 0; i < m; ++i){
add(p[i].u,p[i].v);
}
for (int i = 1; i <= n; ++i){
if (find(i) != find(1))return false;
}
return true;
}
bool cmp(set<int>& a_,set<int>& b_){
return a_.size() > b_.size();
}
int main(){
bool okst = 0;
scanf("%d %d",&n, &m);
for (int i = 0; i < m; ++i){
p[i].read();
}
scanf("%d %d %d %d",&s, &t, &ds, &dt);
int ts = 0,tt = 0;
if (!ok()){
return 0 * puts("No");
}
for (int i = 0; i <= n; ++i)fa[i] = i;
for (int i = 0; i < m; ++i){
int u = p[i].u, v = p[i].v;
if (u == s)g[0].insert(v);
if (v == s)g[0].insert(u);
if (v == t)g[1].insert(u);
if (u == t)g[1].insert(v);
if (u == s && v == t || u == t && v == s)okst = 1;
if (u == s || u == t || v == t || v == s)continue;
if (find(u) != find(v)){
add(u,v);
ans.push_back(make_pair(u,v));
}
}
for (int i = 1; i <= n; ++i){
if (i == s || i == t)continue;
int f = find(i);
bing[f].insert(i);
}
sort(bing+1,bing+n+1,cmp);
for (int i = 1; i <= n; ++i){
if ((int)bing[i].size() == 0)break;
int oks = -1,okt = -1;
for (it = bing[i].begin(); it != bing[i].end(); ++it){
int tm = *it;
if (g[0].count(tm)){
oks = tm;
break;
}
}
for (it = bing[i].begin(); it != bing[i].end(); ++it){
int tm = *it;
if (g[1].count(tm)){
okt = tm;
break;
}
}
if (oks != -1 && okt != -1)Do.push_back(make_pair(oks,okt));
else if (oks != -1){
++ts;
add(oks,s);
ans.push_back(make_pair(oks,s));
}
else if (okt != -1){
++tt;
add(okt,t);
ans.push_back(make_pair(okt,t));
}
}
int len = Do.size();
for (int i = 0; i < len; ++i){
if (ts < ds){
++ts;
ans.push_back(make_pair(Do[i].first,s));
add(s,Do[i].first);
Do[i].first = -1;
}
else {
++tt;
ans.push_back(make_pair(Do[i].second,t));
add(t,Do[i].second);
Do[i].second = -1;
}
}
if (find(s) != find(t) && ts <= ds && tt <= dt){
bool flag = 0;
int len = Do.size();
for (int i = 0; i < len; ++i){
if (ts < ds && Do[i].first != -1){
++ts;
flag = 1;
add(Do[i].first,s);
ans.push_back(make_pair(Do[i].first,s));
break;
}
else if (Do[i].second != -1){
++tt;
flag = 1;
add(Do[i].second,t);
ans.push_back(make_pair(Do[i].second,t));
break;
}
}
if (!flag && okst){
add(s,t);
++ts,++tt;
ans.push_back(make_pair(s,t));
}
}
if (find(s)==find(t) && ts <= ds && tt <= dt) {
puts("Yes");
int hi = ans.size();
for (int i = 0; i < hi; ++i){
printf("%d %d\n",ans[i].first,ans[i].second);
}
}
else puts("No");
return 0;
}
/**
3 2
2 1
3 1
1 2 1 1
10 15
3 2
9 3
9 4
7 3
9 1
5 9
9 8
7 5
5 2
4 3
6 8
7 9
9 10
9 6
5 6
5 9 1 3
**/