CF1559D2 Mocha and Diana (Hard Version) 题解 贪心
\text{Description}
-
给定图
A ,B ,每次操作可在两图内加边(u,v) ,要求两图仍为森林。 -
求最大操作次数和一种方案。
\text{Solution}
很好的贪心题。
不妨令
我们证明
若
对于
那么考虑到
由此贪心分析可知,随意加可行边即可。
因此 D1 就可以直接暴力枚举点对加边即可,时间复杂度
考虑优化贪心。
考虑一个中心点
我们先让所有点与
然后连完后令
显然
考虑
由定义有
那么任意
然后只要随意配对完
时间复杂度
\text{Code}
我写的
const int N=1e5+5;
int n,m1,m2,fa1[N],fa2[N],ans,qaq[N][2],l[N],r[N],cnt1,cnt2;
inline int find1(int x){return fa1[x]==x?x:fa1[x]=find1(fa1[x]);}
inline void merge1(int x,int y){fa1[find1(x)]=find1(y);}
inline int find2(int x){return fa2[x]==x?x:fa2[x]=find2(fa2[x]);}
inline void merge2(int x,int y){fa2[find2(x)]=find2(y);}
// ---------- DSU ---------- //
int main(){
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
// ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
rd(n);rd(m1);rd(m2);
for(re i=1;i<=n;++i) fa1[i]=fa2[i]=i;
for(re i=1;i<=m1;++i){
int x,y;rd(x);rd(y);merge1(x,y);
}
for(re i=1;i<=m2;++i){
int x,y;rd(x);rd(y);merge2(x,y);
}
for(re i=2;i<=n;++i)
if(find1(i)!=find1(1)&&find2(i)!=find2(1)) qaq[++ans][0]=i,qaq[ans][1]=1,merge1(i,1),merge2(i,1);
for(re i=2;i<=n;++i)
if(find1(i)!=find1(1)) l[++cnt1]=i,merge1(i,1);
else if(find2(i)!=find2(1)) r[++cnt2]=i,merge2(i,1);
wr(ans+min(cnt1,cnt2));puts("");
for(re i=1;i<=ans;++i) wr(qaq[i][0]),putchar(' '),wr(qaq[i][1]),puts("");
for(re i=1;i<=min(cnt1,cnt2);++i) wr(l[i]),putchar(' '),wr(r[i]),puts("");
return 0;
}
// ---------- Main ---------- //