SZTU__Vjudge 并查集

A - 并查集

题目大意

现在有一个并查集,让你完成合并和查询操作

思路

并查集模板题

AC代码

#include<bits/stdc++.h>
using namespace std;
const int N = 1e4 + 10;
int p[N];

int find(int x){
	if(p[x] != x) p[x] = find(p[x]);
	return p[x];
}

int main(){
	int n, m;
	cin >> n >> m;
	for(int i = 1;i <= n;i ++){
		p[i] = i;
	}
	while(m --){
		int z, a, b;
		cin >> z >> a >> b;
		if(z == 1){
			if(find(a) == find(b)) continue;
			else p[find(a)] = find(b);
		}else{
			if(find(a) == find(b)) cout << "Y" << endl;
			else cout << "N" << endl;
		}
	}
	return 0;
}

B - 修复公路

题目大意

给出 A 地区的村庄数 NN,和公路数 MM,公路是双向的。并告诉你每条公路的连着哪两个村庄,并告诉你什么时候能修完这条公路。问最早什么时候任意两个村庄能够通车,即最早什么时候任意两条村庄都存在至少一条修复完成的道路(可以由多条公路连成一条道路)。

思路

将每条道路的时间从小到大排序,每次合并道路的时候,都遍历一遍看一看是不是所有的道路都合并了,是的话直接输出此时的时间。

AC代码

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int p[N];
struct node{
    int x, y, t;
}d[N];

bool cmp(node b, node c){
    return b.t < c.t;
}

int find(int x){
    if(p[x] != x) p[x] = find(p[x]);
    return p[x];
}

int main(){
    int n, m;
    cin >> n >> m;
    for(int i = 1;i <= n;i ++){
        p[i] = i;
    }
    for(int i = 0;i < m;i ++){
        cin >> d[i].x >> d[i].y >> d[i].t;
    }
    sort(d, d + m, cmp);
    for(int i = 0;i < m;i ++){
        p[find(d[i].x)] = find(d[i].y);
        int flag = 1;
        for(int j = 1;j < n;j ++){
            if(find(j) != find(j + 1)){
                flag = 0;
            }
        }
        if(flag){
            cout << d[i].t;
            return 0;
        }
    }
    cout << -1;
    return 0;
}

C - 亲戚

题目大意

给出一堆亲戚关系,看任意两人是不是亲戚关系

思路

并查集模板题

AC代码

#include<bits/stdc++.h>
using namespace std;
const int N = 5e3 + 10;
int p[N];

int find(int x){
    if(p[x] != x) p[x] = find(p[x]);
    return p[x];
}

int main(){
    int n, m, q;
    cin >> n >> m >> q;
    for(int i = 1;i <= n;i ++){
        p[i] = i;
    }
    while(m --){
        int a, b;
        cin >> a >> b;
        if(find(a) != find(b)) p[find(a)] = find(b);
    }
    while(q --){
        int a, b;
        cin >> a >> b;
        if(find(a) == find(b)) cout << "Yes" << endl;
        else cout << "No" << endl;
    }
    return 0;
}

D - 一中校运会之百米跑

题目大意

给你一堆名字,然后等一会问你他们是不是在同一组。

思路

并查集模板题

AC思路

#include<bits/stdc++.h>
using namespace std;
const int N = 2e4 + 10;
unordered_map<string,int> q;
int p[N];

int find(int x){
    if(p[x] != x) p[x] = find(p[x]);
    return p[x];
}

int main(){
    int n, m;
    cin >> n >> m;
    for(int i = 1;i <= n;i ++){
        string s;
        cin >> s;
        q[s] = i;
        p[q[s]] = i;
    }
    while(m --){
        string s1, s2;
        cin >> s1 >> s2;
        p[find(q[s1])] = find(q[s2]);
    }
    int k;
    cin >> k;
    while(k --){
        string s1, s2;
        cin >> s1 >> s2;
        if(find(q[s1]) == find(q[s2])) cout << "Yes." << endl;
        else cout << "No." << endl;
    }
    return 0;
}

E - 朋友

题目大意

A 公司有 N 名员工,其中有 P 对朋友关系。B 公司有 M 名员工,其中有 Q 对朋友关系。朋友的朋友一定还是朋友。小明和小红是朋友关系,小明的编号是1,小红的编号是-1,通过小明和小红的这层关系看看最多能凑成多少对情侣。

思路

主要是看看通过小明,a公司有多少人可以和b公司搭上关系,再看看通过小红,b公司有多少人可以和a公司搭上关系,取最小值即可。

AC思路

#include<bits/stdc++.h>
using namespace std;
unordered_map<int,int> p;
unordered_map<int,int> w;

int find(int x){
    if(p[x] != x) p[x] = find(p[x]);
    return p[x];
}

int main(){
    int n, m, t ,q;
    cin >> n >> m >> t >> q;
    for(int i = 1;i <= n;i ++){
        p[i] = i;
    }
    for(int i = -1;i >= -m;i --){
        p[i] = i;
    }
    while(t --){
        int x, y;
        cin >> x >> y;
        if(find(x) != find(y)) p[find(x)] = find(y);
    }
    while(q --){
        int x, y;
        cin >> x >> y;
        if(p[find(x)] != find(y)) p[find(x)] = find(y);
    }
    p[find(1)] = find(-1);
    int ans = 0;
    int cnt = 0;
    for(int i = 1;i <= n;i ++){
        if(find(i) == find(-1)){
            ans ++;
        }
    }
    for(int j = -1;j >= -m;j --){
        if(find(j) == find(1)){
            cnt ++;
        }
    }
    cout << min(ans, cnt);
    return 0;
}

F - 家谱

题目大意

给定一堆字符串,前面是‘#’则表明是父亲,前面是‘+’则表明是儿子,前面是‘?’则是询问这个人的祖宗是谁。

思路

并查集模板题,唯一可能要注意的点就是用一下map而已。

AC代码

#include<bits/stdc++.h>

using namespace std;

string s;
map<string,string> p;
string father;

string find(string x){
    if(p[x] != x) p[x] = find(p[x]);
    return p[x];
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    while(cin >> s && s != "$"){
        if(s[0] == '#'){
            father = s.substr(1);
            if(p[father] == "") p[father] = father;
        }
        else if(s[0] == '+'){
            string x = s.substr(1);
            p[x] = find(father);
        }else{
            string x = s.substr(1);
            cout << x << " " << find(x) << "\n";
        }
    }
    return 0;
}
  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
写一个命令行交互式C语言程序。该程序需要实现下述菜单功能: 1. 数据存储。 你需要将一系列的学生期末考试信息进行存储(学生人数不会超过100)。每个学生的信息包括:姓名 (由first name 和last name 两部分组成,例如Jingyu LI,first_name = "Jingyu" last_name = "LI") ;学号(12位数字组成,开头4位为2022、2021、2020);C语言成绩(一个大于等于零的整数);重 修信息(学号2022………为否,其余为是);GPA等级(A+, A, B+, B, C+, C, D, F );班级排名(成绩相 同需并列)。其中,姓名,学号,成绩为输入数据,其余数据需要你计算。 同时,你需要添加一些维护数据库的功能 Add(name, id, score): 新增一个学生的信息; Delete(id): 根据学号删除某个学生的信息; Search(id):根据学号查找某个学生的信息。 2. 数据处理。 Sort_by_score(): 生成根据分数由高到低顺序排列学生信息的表格 3. 数据加密和解密 char* encrypt(int key): 加密学生成绩并返回 char* decrypt(int key, char *str): 解密学生成绩并返回 加密规则:把所有学生的成绩拼接成一个只包含数字的字符串,然后依据整数key对其进行加密。例 如:数字1被key=5加密之后变成6;数字5被key=5加密之后变成0。单个数字加密之后仍是单个数字。 解密规则与加密规则对称。 4. 数据分析 根据GPA对学生成绩进行考情分析:A+多少人,A多少人,以此类推。GPA等级参考SZTU评分等级。 5. 用户界面 实现一个菜单,以供用户决定要使用哪个功能。
06-12
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值