zoukankan      html  css  js  c++  java
  • CF1559D1. Mocha and Diana (Easy Version)

    原题链接:1559D1. Mocha and Diana (Easy Version)

    题意:

    小明和小红各有一个具有(n)个结点的森林,现执行操作:

    • 加一条边,使得两人的森林还是森林
    • 小明加一条((u, v))的边,那么小红也必须加一条((u, v))的边。
      问我们最多能加多少边?

    思路:

    很明显,第一个条件没啥用,关键是第二个条件,我们知道如果一个人不能加((u, v))一条边的前提条件是(u)(v)已经联通,那么根据这个条件,我们可以使用并查集,而边的数据范围是([1-1000]),所以可以直接暴力枚举点,然后使用并查集来判断两个点是否已经在一个集合内,如果在一个集合内那么就不能加边了,否则加上即可。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int N = 1010;
    int fa1[N], fa2[N];
    
    int find1(int x) {
    	if (x != fa1[x]) fa1[x] = find1(fa1[x]);
    	return fa1[x];
    }
    
    int find2(int x) {
    	if (x != fa2[x]) fa2[x] = find2(fa2[x]);
    	return fa2[x];
    }
    
    int main() {
    	ios::sync_with_stdio(false), cin.tie(0);
    	
    	int n, m1, m2;
    	cin >> n >> m1 >> m2;
    	for (int i = 1; i <= n; i++) fa1[i] = i, fa2[i] = i;
    	while (m1--) {
    		int a, b;
    		cin >> a >> b;
    		fa1[find1(a)] = find1(b);
    	}
    	
    	while (m2--) {
    		int a, b;
    		cin >> a >> b;
    		fa2[find2(a)] = find2(b);
    	}
    	
    	vector<pair<int, int>> add;
    	for (int i = 1; i <= n; i++) {
    		for (int j = i + 1; j <= n; j++) {
    			int u1 = find1(i), v1 = find1(j);
    			int u2 = find2(i), v2 = find2(j);
    			if (u1 != v1 && u2 != v2) {
    				add.push_back({i, j});
    				fa1[u1] = v1;
    				fa2[u2] = v2;	
    			}
    		}
    	}
    	
    	cout << add.size() << endl;
    	for (int i = 0; i < add.size(); i++) 
    		cout << add[i].first << " " << add[i].second << endl;
    	
        return 0;
    }
    

    注意:

    题目思路并不难,但是我耗了一个多小时,原因:
    我一开始(find)函数写成了这样。

    int find1(int x) {
    	if (x == fa1[x]) return x;
    	return find1(fa1[x]);
    }
    

    乍一看没错,确实没错,就是(T)到飞起,为啥,因为没有加入路径压缩的优化,所以(T)到飞起,我服了,这次长记性了。
    另外,以后并查集用一个类吧,贴个板子:

    struct DSU{
    	int fa[N], Size[N];
    	void init() {
    		for (int i = 1; i <= n; i++) fa[i] = i;
    	}
    	int find(int x) {
    		if (x != fa[x]) fa[x] = find(fa[x]);
    		return fa[x];
    	}
    	void merge(int x, int y) {
    		Size[find(x)] += Size[find(y)];
    		fa[find(x)] = find(y);
    	}
    	bool check(int x, int y) {
    		return find(x) == find(y);
    	}
    }dsu1, dsu2;
    
  • 相关阅读:
    图与图算法在实际中的应用
    python Tricks —— list 镜像复制与 list comprehension 列表解析的顺序
    C语言高速入门系列(五)
    Linked List Cycle
    poj 2689 Prime Distance(大区间筛素数)
    三层结构——理论篇
    史上最简单的Hibernate入门简单介绍
    [SQL]远程使用PostgreSQL Studio可视化查看PostgreSQL数据库
    MySQL建立双向主备复制server配置方法
    win2003的IIS無法使用,又一次安裝提示找不到iisadmin.mfl文件
  • 原文地址:https://www.cnblogs.com/ZhengLijie/p/15146455.html
Copyright © 2011-2022 走看看