【生成树趣题】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 ...
随机推荐
- 零拷贝的原理及Java实现
在谈论Kafka高性能时不得不提到零拷贝.Kafka通过采用零拷贝大大提供了应用性能,减少了内核和用户模式之间的上下文切换次数.那么什么是零拷贝,如何实现零拷贝呢? 什么是零拷贝 WIKI中对其有如下 ...
- PowerDesigner 生成SQL Server 注释脚本
--生成数据表的注释EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=[%R%?[N]]%.q:COMMENT% , @l ...
- 从hive中读取数据推送到kafka
由python2.7语言实现的,包也比较旧了. # -*- coding: utf-8 -*- # Version: 1.0.0 # Description: py_Hive2Kafka2kafka ...
- Python 3标准库 第十一章 网路通信
网路通信11.1 ipaddress : Internet 地址 ipaddress模块提供了处理IPv4和IPv6 11.1.2 网络 CMDB 11.2 socket:网络通信 11.2. ...
- IE ActiveObject
ActiveObject只能用于基于IE内核的浏览器 需要添加信任站点 并设置对ActiveObject的启用 问题: 1.用javascript 创建ActiveX对象时出现:Automation ...
- 计算机网络(十一),HTTP和HTTPS区别
目录 1.SSL(Security Sockets Layer,安全套接层) 2.加密方式 3.HTTPS数据传输流程 4.HTTP和HTTPS的区别 5.HTTP真的很安全吗 十一.HTTP和HTT ...
- 【杂题】[AGC034D] Manhattan Max Matching【费用流】
Description 有一个无限大的平面,有2N个位置上面有若干个球(可能重复),其中N个位置是红球,N个位置是蓝球,红球与蓝球的总数均为S. 给出2N个位置和上面的球数,现要将红球与蓝球完美匹配, ...
- sh_07_元组遍历
sh_07_元组遍历 info_tuple = ("zhangsan", 18, 1.75) # 使用迭代遍历元组 for my_info in info_tuple: # 使用格 ...
- 2-sat基础详解
(大量引用<2-SAT解法浅析 -by 华中师大一附中 赵爽><由对称性解2-SAT问题> Great_Influence关于P4782 [模板]2-SAT 问题的题解.在此对 ...
- Linux命令-磁盘管理(一)
Linux命令-磁盘管理(一) Linux cd命令 Linux cd命令用于切换当前工作目录至 dirName(目录参数). 其中 dirName 表示法可为绝对路径或相对路径.若目录名称省略,则变 ...