【生成树趣题】CF723F st-Spanning Tree
题意:
给定一个n个点m条边的无向联通图,没有重边和自环。给定s和t,求一棵生成树,使得s,t的度数不超过ds,dt。若有解,输出“Yes”和方案(多组方案输出任意一组),若无解,输出“No”。
数据范围:
2 ≤ n ≤ 200 000
分析:
首先,可以把边分成两类:一类是端点含s或t的,另一类是和s,t没有任何关系的。第二类边可以随便乱连,而第一类边不可以。
所以,就先把第二类边乱连,随便连,反正没有边权连就是了,用一个并查集,相当于搞一个生成树森林出来,这样我们就有了很多很多块集合(相当于被缩成一个点,要注意细节)和s,t两个点。
集合中只与s,t的其中一个点有边的,只能连那个边,否则就不联通了。一边连一边判断s,t的度数,如果超过了就判定无解。
集合中和s,t都有边相连的,选一个和s,t都连一条边,这样可以使s,t联通的同时尽量最小化度数。(s,t直接相连,度数各增加1,某一个集合再和s,t中的一个相连,s,t中的一个度数会增加1)
剩下的和s,t都有边相连的集合,随便连s,t都可以。(如果一个点的度数被连完了,就连另外那个)
最后,如果没有和s,t都有边相连的集合,那么此时s,t还没有被连起来,那么还要在s,t之间直接连一条边。
注意还要判断它是不是一棵生成树的形态(边数为n-1)
#include<cstdio>
#include<iostream>
#include<iomanip>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define N 200005
int n,m,s,t,ds,dt;
vector<int>G[N];
vector<pair<int,int> >ans;
int f[N];//并查集
int ls[N],lt[N];//编号为i的集合通过ls[i]/lt[i]和s/t相连
inline int rd()
{
int f=,x=;char c=getchar();
while(c<''||''<c){if(c=='-')f=-f;c=getchar();}
while(''<=c&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return f*x;
}
int Find(int x)
{
if(f[x]==x) return x;
return f[x]=Find(f[x]);
}
bool Union(int u,int v)
{
int x=Find(u),y=Find(v);
if(x==y) return false;
if(x<y) f[y]=x;
else f[x]=y;
return true;
}
void Init()
{
for(int i=;i<=n;i++)
f[i]=i;
}
int main()
{
n=rd(),m=rd();
for(int i=;i<=m;i++)
{
int u=rd(),v=rd();
G[u].push_back(v);
G[v].push_back(u);
}
s=rd(),t=rd(),ds=rd(),dt=rd();
Init();
//乱连不含s,t的边
for(int u=;u<=n;u++)
{
if(u==s||u==t) continue;
for(int i=;i<G[u].size();i++)
{
int v=G[u][i];
if(v==s||v==t) continue;
if(Union(u,v)) ans.push_back(make_pair(u,v));
}
}
//处理集合的哪些边和s,t相连的情况
for(int i=;i<G[s].size();i++)
if(G[s][i]!=t)
{
int x=Find(G[s][i]);
ls[x]=G[s][i];
}
for(int i=;i<G[t].size();i++)
if(G[t][i]!=s)
{
int x=Find(G[t][i]);
lt[x]=G[t][i];
}
//处理只和s,t中的一个相连的集合
for(int i=;i<=n;i++)
{
if(ls[i]&&!lt[i])
{
ds--;
Union(s,i);
ans.push_back(make_pair(s,ls[i]));
}
else if(!ls[i]&<[i])
{
dt--;
Union(t,i);
ans.push_back(make_pair(t,lt[i]));
}
if(ds<||dt<)
{
puts("No");
return ;
}
}
//处理和s,t都相连的集合 第一个会和s,t都连 s,t连通之后就只会连一个
for(int i=;i<=n;i++)
if(ls[i]&<[i])
{
if(ds&&Union(s,i))
{/*短路运算符 Union不能写在前面 或者也可以用find()判断 Union写在里面*/
ds--;
ans.push_back(make_pair(s,ls[i]));
}
if(dt&&Union(t,i))
{
dt--;
ans.push_back(make_pair(t,lt[i]));
}
if(Find(s)!=Find(i)||Find(t)!=Find(i)) //说明前面没有办法连 度数都用完了
{
puts("No");
return ;
}
}
if(Find(s)!=Find(t))//s,t还没有连通
{
bool f=;
for(int i=;i<G[s].size();i++)
if(G[s][i]==t)
{
f=;
break;
}
if(ds&&dt&&f)
ans.push_back(make_pair(s,t));
if(!f)
{
puts("No");
return ;
}
}
if(ans.size()!=n-)
{//满足是一棵生成树
puts("No");
return ;
}
puts("Yes");
for(int i=;i<ans.size();i++)
printf("%d %d\n",ans[i].first,ans[i].second);
return ;
}
Code
【生成树趣题】CF723F st-Spanning Tree的更多相关文章
- AtCoder Regular Contest 093 E: Bichrome Spanning Tree(生成树)
Bichrome Spanning Tree 题意: 给出一个n个点,m条边的无向连通图,现在要给每条边染色,可以染成黑色或者白色. 现在要求在染色完毕后,找出一个至少包含一条黑边和一条白边的最小生成 ...
- 【HDU 4408】Minimum Spanning Tree(最小生成树计数)
Problem Description XXX is very interested in algorithm. After learning the Prim algorithm and Krusk ...
- 数据结构与算法分析–Minimum Spanning Tree(最小生成树)
给定一个无向图,如果他的某个子图中,任意两个顶点都能互相连通并且是一棵树,那么这棵树就叫做生成树(spanning tree). 如果边上有权值,那么使得边权和最小的生成树叫做最小生成树(MST,Mi ...
- CF# Educational Codeforces Round 3 E. Minimum spanning tree for each edge
E. Minimum spanning tree for each edge time limit per test 2 seconds memory limit per test 256 megab ...
- HDU 4408 Minimum Spanning Tree 最小生成树计数
Minimum Spanning Tree Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Ot ...
- STP(Spanning Tree Protocol)
STP生成树协议 问题 为了提高网络的可用性,需要进行冗余和备份.但是冗余路径会产生环路 环路会导致以下问题 广播风暴:由于交换机会对广播.多播.和未知目标MAC的单播包进行泛洪,在存在环路的情况 ...
- [Educational Round 3][Codeforces 609E. Minimum spanning tree for each edge]
这题本来是想放在educational round 3的题解里的,但觉得很有意思就单独拿出来写了 题目链接:609E - Minimum spanning tree for each edge 题目大 ...
- [BZOJ3080]Minimum Variance Spanning Tree/[BZOJ3754]Tree之最小方差树
[BZOJ3080]Minimum Variance Spanning Tree/[BZOJ3754]Tree之最小方差树 题目大意: 给定一个\(n(n\le50)\)个点,\(m(m\le1000 ...
- Educational Codeforces Round 3 E. Minimum spanning tree for each edge 最小生成树+树链剖分+线段树
E. Minimum spanning tree for each edge time limit per test 2 seconds memory limit per test 256 megab ...
随机推荐
- myeclipse 工具栏 Run按钮不见了,怎么调出来啊?
window-->new window,打开新窗口,按钮出现了.关闭老窗口,再关闭新窗口.再次打开MyEclipse,妥妥的了.
- 【LuoguP5383】[模板]普通多项式转下降幂多项式
传送门 Sol (怎么老是有人喜欢出新的多项式毒瘤板子,懒得整到一起了) 核心就是把 幂用下降幂来代替. 使用斯特林数展开幂为下降幂: \[x^n=\sum_{i=0}^n{x\choose i}i! ...
- d3 词云使用
D3-Cloud是一个开源的词云实现,基于D3.js,使用HTML5 Canvas绘制输出,因为采用异步的方式处理,所以表现性能良好. 项目主页:https://www.jasondavies.com ...
- Linux 系统中 grep 的ABC参数含义
1.grep -A 5 匹配行及后5行 2.grep -B 5 匹配行及前5行 3.grep -C 5 匹配行及前后各5行
- QT:QSS ID选择器无效
我正在学习使用Qt样式表给我的应用程序添加不同的样式.我上网看了看Qt文档,上面说你可以使用一种ID选择器,它可以把主题应用到某些对象上.我就是这样实现这个特性的: QPushButton#butto ...
- Qt:路径问题小结
在做Qt项目的时候,我们难免遇到到文件路径问题. 如QFile file("text.txt")加载不成功.QPixmap("../text.png") 加载图 ...
- DOM导航与DOM事件
HTML DOM 导航 通过 HTML DOM,能够使用节点关系在节点树中导航. ㈠HTML DOM 节点列表 getElementsByTagName() 方法返回节点列表.节点列表是一个节点数组. ...
- hexdump命令
hexdump hexdump用于以16进制.10进制.8进制.ascii码形式打印文件内容,也可以是标准输入的内容. 用法 hexdump [选项] 文件 ... 选项 选项 参数 说明 -b ...
- cgi 检索Cookie信息
Cookie信息检索页非常简单,Cookie信息存储在CGI的环境变量HTTP_COOKIE中,存储格式如下: key1=value1;key2=value2;key3=value3.... 以下是一 ...
- fiddler(二)、配置抓取https协议
打开fiddler,用火狐或者谷歌浏览器访问https协议的网页,如:https://www.baidu.com/,会报不安全的连接错误 这时就需要我们做一些配置,才能抓取https协议的网页. 首先 ...