题目传送门

题意:

给定一个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]&&lt[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]&&lt[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的更多相关文章

  1. AtCoder Regular Contest 093 E: Bichrome Spanning Tree(生成树)

    Bichrome Spanning Tree 题意: 给出一个n个点,m条边的无向连通图,现在要给每条边染色,可以染成黑色或者白色. 现在要求在染色完毕后,找出一个至少包含一条黑边和一条白边的最小生成 ...

  2. 【HDU 4408】Minimum Spanning Tree(最小生成树计数)

    Problem Description XXX is very interested in algorithm. After learning the Prim algorithm and Krusk ...

  3. 数据结构与算法分析–Minimum Spanning Tree(最小生成树)

    给定一个无向图,如果他的某个子图中,任意两个顶点都能互相连通并且是一棵树,那么这棵树就叫做生成树(spanning tree). 如果边上有权值,那么使得边权和最小的生成树叫做最小生成树(MST,Mi ...

  4. 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 ...

  5. HDU 4408 Minimum Spanning Tree 最小生成树计数

    Minimum Spanning Tree Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Ot ...

  6. STP(Spanning Tree Protocol)

    STP生成树协议   问题 为了提高网络的可用性,需要进行冗余和备份.但是冗余路径会产生环路 环路会导致以下问题 广播风暴:由于交换机会对广播.多播.和未知目标MAC的单播包进行泛洪,在存在环路的情况 ...

  7. [Educational Round 3][Codeforces 609E. Minimum spanning tree for each edge]

    这题本来是想放在educational round 3的题解里的,但觉得很有意思就单独拿出来写了 题目链接:609E - Minimum spanning tree for each edge 题目大 ...

  8. [BZOJ3080]Minimum Variance Spanning Tree/[BZOJ3754]Tree之最小方差树

    [BZOJ3080]Minimum Variance Spanning Tree/[BZOJ3754]Tree之最小方差树 题目大意: 给定一个\(n(n\le50)\)个点,\(m(m\le1000 ...

  9. 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 ...

随机推荐

  1. P1801 黑匣子[对顶堆]

    没错我就是专门找对顶堆练习题的.现在感觉对顶堆使用面有点狭窄.这道题由于我询问是随时间单调增的,而且数据比较友好,应该是插入几次就询问一下的.而中位数那题也是经常询问的.如果查询的东西不单调,或者查询 ...

  2. 【每日一包0003】kind-of

    github地址:https://github.com/ABCDdouyae... kind-of 判断数据类型用法:kind-of(date)返回:string 数据类型 January undef ...

  3. IPC 进程间通信方式——管道

    进程间通信概述 数据传输:一个进程需要将它的数据发送给另一个进程,发送的数据量在一个字节到几兆字节之间 共享数据:多个进程想要操作共享数据,一个进程对共享数据的修改,别的进程应该立刻看到. 通知时间: ...

  4. Acwing-283-多边形(区间DP)

    链接: https://www.acwing.com/problem/content/285/ 题意: "多边形游戏"是一款单人益智游戏. 游戏开始时,给定玩家一个具有N个顶点N条 ...

  5. Matlab的基本矩阵运算

    (1)加减.数乘 >> a=[1,2;3,4];b=[5,6;7,8]; >> a+b ans = 6 8 10 12 >> a.*2 ans = 2 4 6 8 ...

  6. java——解决"java.io.StreamCorruptedException: invalid stream header: xxx"

    这个错误是由序列化引起的,可能的原因以及解决方法: 1.kryo对于集合(比如 Map)的反序列化会失效,报这个错误,解决办法比较暴力,不用kryo了,直接用java原生方法. 2.使用Java原生方 ...

  7. Tomcat部署多个Springboot项目报错 InstanceNotFoundException: com.alibaba.druid:type=DruidDataSourceStat

    在一个tomcat服务器下部署了多个采用阿里druid作为数据连接池,结果启动报错.原因是不能在一个tomcat服务器下不能直接部署多个druid作为数据连接池的项目,需要配置. 解决办法: 在spr ...

  8. 【leetcode】960. Delete Columns to Make Sorted III

    题目如下: We are given an array A of N lowercase letter strings, all of the same length. Now, we may cho ...

  9. Harbor ($docker login) Error saving credentials

    $ sudo apt-get install $ sudo apt-get install gnupg2 pass 问题解决!

  10. wx小程序知识点(三)

    三.封装小程序的数据请求 (1)在根目录创建utils目录,创建config.js.base.js (2)在config.js中创建config类,并将请求路径配置给config的属性restUrl, ...