ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

CF1559D2 - Mocha and Diana(构造)

2021-08-17 12:03:50  阅读:170  来源: 互联网

标签:rt 结点 CF1559D2 Diana Mocha int m2 define 森林


题目

Problem - D2

给定两个不同的分别包含\(n\)个点的森林,每次可以同时在两个森林加一条相同的边,加边过程中不能出现环。问最多能加多少边,输出任一方案。\(n\le 10^5\)

题解

在submission上看到一个很吊的做法。

先确定一个根\(rt\),比如1号结点,然后遍历每个点\(u\),有三种情况:

  • \(u\)在两个森林中都和\(rt\)连了,那么不用再连;
  • \(u\)在两个森林中都不与\(rt\)相连,那么连上,添加答案\((u,rt)\)
  • \(u\)在其中一个森林和\(rt\)相连,另一个不连,那么先插入一个栈保存起来。

需要两个并查集和两个栈,上述操作完成后,两栈内结点再互相连接并加入答案。

这个方法是正确的,因为第一次遍历操作完后,左边的森林中剩余的没和\(rt\)相连结点和右边的同样的结点交集为空。问题最优结果是其中一个森林变成树。这个算法可以保证最终一定有个森林最后会变成一个树且都是合法的。

还有各种方法,这个方法虽然简单,但是确实难想到。

#include <bits/stdc++.h>
 
#define endl '\n'
#define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define mp make_pair
#define seteps(N) fixed << setprecision(N)
typedef long long ll;
 
using namespace std;
/*-----------------------------------------------------------------*/
 
ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
#define INF 0x3f3f3f3f
 
const int N = 3e5 + 10;
const double eps = 1e-5;
 
int fa1[N];
int fa2[N];
 
int find(int x, int fa[]) {
    if(x == fa[x]) return fa[x];
    return fa[x] = find(fa[x], fa);
}
 
void merge(int u, int v, int fa[]) {
    int fu = find(u, fa), fv = find(v, fa);
    if(fu != fv) fa[fu] = fv;
}
 
typedef pair<int, int> PII;
vector<PII> ans;
stack<int> v1, v2;
 
int main() {
    IOS;
    int n, m1, m2;
    cin >> n >> m1 >> m2;
    for(int i = 1; i <= n; i++) {
        fa1[i] = fa2[i] = i;
    }
    for(int i = 0; i < m1; i++) {
        int u, v;
        cin >> u >> v;
        merge(u, v, fa1);
    }
    for(int i = 0; i < m2; i++) {
        int u, v;
        cin >> u >> v;
        merge(u, v, fa2);
    }
    int rt = 1;
    for(int i = 1; i <= n; i++) {
        if((find(i, fa1) != find(rt, fa1)) && (find(i, fa2) != find(rt, fa2))) {
            ans.push_back({rt, i});
            merge(i, rt, fa1);
            merge(i, rt, fa2);
        }
    }
    for(int i = 1; i <= n; i++) {
        if((find(i, fa1) != find(rt, fa1)) && (find(i, fa2) == find(rt, fa2))) v1.push(i);
        if((find(i, fa1) == find(rt, fa1)) && (find(i, fa2) != find(rt, fa2))) v2.push(i);
    }
    while(!v1.empty() && !v2.empty()) {
        ans.push_back({v1.top(), v2.top()});
        merge(v1.top(), v2.top(), fa1);
        merge(v1.top(), v2.top(), fa2);
        while(!v1.empty() && (find(v1.top(), fa1) == find(rt, fa1))) v1.pop();
        while(!v2.empty() && (find(v2.top(), fa2) == find(rt, fa2))) v2.pop();
    }
    cout << ans.size() << endl;
    for(auto res : ans) cout << res.first << " " << res.second << endl;
}

标签:rt,结点,CF1559D2,Diana,Mocha,int,m2,define,森林
来源: https://www.cnblogs.com/limil/p/15151681.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有