Codeforces Round #375 (Div. 2) F. st-Spanning Tree(给你n个点,m条边,有两个给定的点S,T以及它们在生成树中最大的度数)
2016-10-04 20:19
567 查看
传送门:Codeforces Round #375 (Div. 2) F. st-Spanning Tree
题意:
给你n个点,m条边,有两个给定的点S,T以及它们在生成树中最大的度数
求能否构造出一棵树,使得这两个点的度数满足要求
思路:
求出不使用与S,T有关的边构成的联通块
这些联通块与S,T有三种联通情况
1.只与S相连
2.只与T相连
3.与S和T均相连
记录一下已经使用的边的数量就可以了
题意:
给你n个点,m条边,有两个给定的点S,T以及它们在生成树中最大的度数
求能否构造出一棵树,使得这两个点的度数满足要求
思路:
求出不使用与S,T有关的边构成的联通块
这些联通块与S,T有三种联通情况
1.只与S相连
2.只与T相连
3.与S和T均相连
记录一下已经使用的边的数量就可以了
#include<bits/stdc++.h> using namespace std; const int N=5e5+10; struct Edge{ int from,to; }e ; vector<Edge>tmp,ans,mp ; int f ,flag ; int find(int x){ return f[x]==x ? x:f[x]=find(f[x]); } int main(){ int n,m,s,t,ds,dt,degree_s=0,degree_t=0; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) f[i]=i; for(int i=1;i<=m;i++) scanf("%d%d",&e[i].from,&e[i].to); scanf("%d%d%d%d",&s,&t,&ds,&dt); //构造出与S,T无关的若干个联通块 for(int i=1;i<=m;i++){ if(e[i].from==s||e[i].to==s||e[i].from==t||e[i].to==t) tmp.push_back(e[i]); else{ int x=find(e[i].from),y=find(e[i].to); if(x!=y) f[x]=y,ans.push_back(e[i]); } } bool Sta=false;//标记是否有S-T这条边 for(int i=0;i<tmp.size();i++){ if(tmp[i].to==s||tmp[i].to==s||tmp[i].to==t||tmp[i].to==t) swap(tmp[i].from,tmp[i].to); int x=find(tmp[i].from),y=find(tmp[i].to); if(x+y==s+t) Sta=true; else if(x==s) flag[y]|=1,mp[y].push_back(tmp[i]); else if(y==s) flag[x]|=1,mp[x].push_back(tmp[i]); else if(x==t) flag[y]|=2,mp[y].push_back(tmp[i]); else if(y==t) flag[x]|=2,mp[x].push_back(tmp[i]); } for(int i=1;i<=n;i++){ if(flag[i]==1){ //只与S相连 degree_s++; ans.push_back(mp[i][0]); } else if(flag[i]==2){//只与T相连 degree_t++; ans.push_back(mp[i][0]); } } bool Flag=false; for(int i=1;i<=n;i++) if(flag[i]==3){ if(Flag==false){ int cnt=0; for(int j=0;j<mp[i].size();j++){ if(mp[i][j].from==s&&(cnt&1)==0) ans.push_back(mp[i][j]),cnt|=1; else if(mp[i][j].from==t&&(cnt&2)==0) ans.push_back(mp[i][j]),cnt|=2; } degree_s++,degree_t++; Flag=true; } else{ int st=ds-degree_s < dt-degree_t ? t:s; for(int j=0;j<mp[i].size();j++) if(mp[i][j].from==st){ ans.push_back(mp[i][j]); break; } st==t ? ++degree_t:++degree_s; } } if(Flag==false&&Sta){ degree_s++,degree_t++; ans.push_back((Edge){s,t}); } if(degree_s<=ds&°ree_t<=dt&&ans.size()==n-1){ printf("Yes\n"); for(int i=0;i<ans.size();i++) printf("%d %d\n",ans[i].from,ans[i].to); } else printf("No\n"); return 0; }
相关文章推荐
- 给定两个数m,n,使用欧几里得的辗转相除法求出它们的最大公约数
- 算法如功夫——C++输入两个数求它们的最大公约数
- 判断两个矩形相交以及求出相交的区域(生成的相交矩形)
- 关于DIV中display属性误区以及牵扯出来的两个问题
- 给定一个数组input[] ,如果数组长度n为奇数,则将数组中最大的元素放到 output[] 数组 最中间的位置,如果数组长度n为偶数,则将数组中最大的元素放到 output[] 数组中间两个位置偏右的那个位置上
- 【Java】给定两个32位的整数N与M,以及表示比特位置的i与j。编写一个方法,将M插入N,使得M从N的第 j 位开始,到第 i 位结束。
- 从键盘上输入5个数,输出最大、最小元素的值以及它们的下标
- 为什么会有OutputStreamWriter和InputStreamReader两个转换类的出现以及它们的作用
- 计算机设计与艺术——给定两个正整数,求它们最大公因子
- 已知两个链表head1 和head2 各自有序,请把它们合并成一个链表依然有序。使用非递归方法以及递归方法。
- 输入两个正整数,求它们的最大公约数和最小公倍数.
- C++初学之 4.生成类以及类的派生(两个基类,一个多重派生类)
- 给定两个输入文本,找出它们共有的最长字符串
- 同时寻找最大数和最小数的最优算法以及寻找最大的两个数所需的最少比较次数
- 使用PS切片工具进行切片生成div布局的页面的方法以及如何确定图片中某个点在图片中的位置
- 任意给定一整数数组,求两个元素之差的最大值和数组中出现次数最多的数
- 判断两个数值中最大的一个以及不用中间变量交换两个数
- 一个字符串A的子串被定义成从A中顺次选出若干个字符构成的串。如A=“cdaad" ,顺次选1,3,5个字符就构成子串" cad" ,现给定两个字符串,求它们的最长共公子串。 小王对既是素数又是回文的
- 【WorkTile赞助】jQuery编程挑战#009:生成两个div元素互相追逐的动画
- [置顶] 关于不同对象且属性名称也不一样的两个对象之间的复制以及动态对象生成