当前位置: 首页 > article >正文

图论三元环(并查集的高级应用)

题目描述

无聊的你回想起了A题的三角形,于是你想到了一个新的问题:

在一个连通图中,任何一条边都属于一个集合

如果两条边 a,b属于同一个集合当且仅当满足以下条件之一

1.  a,b 是某一个三角形的两条边

2. 存在边 c ,使得 a,c 属于同一个集合且 b,c 属于同一个集合

那么请问,以下连通图的所有边是否都属于同一个集合?

输入描述:

第一行输入 T,表示 T 组样例

每组样例第一行输入两个正整数 n,m

接下来 m 行,第i行输入两个正整数 ai,bi​,表示第i条边连接 ai,bi​结点

数据保证图联通,且没有重边和自环

输出描述:

输出一个字符串表示答案

是输出 "Yes"

否输出 "No"

示例1

输入

1
3 3
1 2
1 3
3 2

输出

Yes

示例2

输入

1
4 5
1 2
1 4
2 3
2 4
3 4

输出

Yes

示例3

输入

1
3 2
1 2
1 3

输出

No

示例4

输入

1
4 4
1 2
1 4
2 3
3 4

输出

No

先放在这里

代码:

#include <bits/stdc++.h>
using namespace std; // 引入 std 命名空间

using i64 = long long;
using u64 = unsigned long long;

void solve() {
    int n, m;
    cin >> n >> m;
    vector<int> p(m + 1);

    auto find = [&] (auto self, int &x) -> int {
        if (x == p[x]) return x;
        return p[x] = self(self, p[x]);
    };

    auto merge = [&] (int &a, int &b) -> void {
        int fa = find(find, a), fb = find(find, b);
        if (fa != fb) {
            p[fb] = fa;
        }
    };

    vector<int> in(n + 1), u(m + 1), v(m + 1);

    for (int i = 1; i <= m; i++) {
        cin >> u[i] >> v[i];
        in[u[i]]++;
        in[v[i]]++;
        p[i] = i;
    }

    vector<vector<pair<int, int>>> e(n + 1);

    for (int i = 1; i <= m; i++) {
        if (in[u[i]] < in[v[i]] || (in[u[i]] == in[v[i]] && u[i] < v[i])) {
            e[v[i]].push_back({u[i], i});
        } else {
            e[u[i]].push_back({v[i], i});
        }
    }

    vector<pair<int, int>> vis(n + 1);

    for (int i = 1; i <= n; i++) {
        for (auto [x, j] : e[i]) vis[x] = {i, j};

        for (auto [x, j] : e[i]) {
            for (auto [y, k] : e[x]) {
                if (vis[y].first == i) {
                    merge(k, j);
                    merge(j, vis[y].second);
                }
            }
        } 
    }

    int ans = 0;
    for (int i = 1; i <= m; i++) {
        if (p[i] == i) ans++;
    }

    if (ans == 1) cout << "Yes\n";
    else cout << "No\n";
}

int main() {
    ios::sync_with_stdio(0);
    cout.tie(0);
    cin.tie(0);

    i64 t = 1; 
    cin >> t;
    while (t--) {
        solve();
    }
}


http://www.kler.cn/news/312229.html

相关文章:

  • 天润融通创新功能,将无效会话转化为企业新商机
  • 青柠视频云——视频丢包(卡顿、花屏、绿屏)排查
  • Python 集合的魔法:解锁高效数据处理的秘密
  • 工厂模式(一):简单工厂模式
  • Web后端服务平台解析漏洞与修复、文件包含漏洞详解
  • 【Git原理与使用】多人协作与开发模型(2)
  • 杀死端口占用的进程
  • 常用函数式接口的使用
  • 3D GS 测试自己的数据
  • react 甘特图之旅
  • C语言 | Leetcode C语言题解之第405题数字转换为十六进制数
  • SpringBoot 数据库表结构文档生成
  • 深入Redis:核心的缓存
  • 【计算机网络 - 基础问题】每日 3 题(十四)
  • 百易云资产系统 house.save.php SQL注入
  • tomcat知识
  • 【Android】ViewPager
  • 生信初学者教程(三):介绍
  • [Linux] 进程优先级 进程的调度与切换 环境变量详解
  • qt--Qml控件库如何从外部导入
  • 虾皮选品技巧有哪些?超全Shopee选品的方法和技巧分享!
  • C#无标题栏窗体拖动
  • 物联网开发+充电桩管理系统+充电桩系统源码
  • 【北京迅为】《STM32MP157开发板使用手册》- 第四十二章 事件实验
  • Java设计模式—面向对象设计原则(四) ----->接口隔离原则(ISP) (完整详解,附有代码+案例)
  • 基于JavaWeb开发的java+Springboot操作系统教学交流平台详细设计实现
  • 探索AI大模型的未来:电信运营商与云服务商的新征途@附58页PDF文件下载
  • liunx 计划任务
  • VRRP协议原理
  • 《计算机网络名词解释》