传送门
题意
给你一些线段,把线段当成点,当线段相交时认为两个点相连,要求你判断最后生成的这个图是否是一颗树。
题解
- 树有
N-1
条边所以可以暴力建图,当边数>N-1
时直接输出NO
即可- 排序之后用
SET
保存之前的边右端点和编号,当节点相连时用并查集判断是否有环,当边数>N-1
或存在环时输出NO
- 因为有存在是森林的情况所以判断边数是否小于
N-1
- 排序之后用
C++
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <stack>
#include <string>
#include <queue>
#include <map>
#include <set>
#include <cmath>
using namespace std;
const int N = 5e5 + 50;
int n, p[N];
pair<int, int> a[N];
set<pair<int, int>> s;
int find(int x)
{
return p[x] == 0 ? x : p[x] = find(p[x]);
}
bool merge(int x, int y)
{
x = find(x), y = find(y);
if (x == y)
return false;
p[x] = y;
return true;
}
int main()
{
#ifdef ONLINE_JUDGE
#else
freopen("r.txt", "r", stdin);
#endif
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%d%d", &a[i].first, &a[i].second);
sort(a + 1, a + n + 1);
int num = 0;
for (int i = 1; i <= n; i++)
{
for (auto p = s.upper_bound(make_pair(a[i].first, 0)); p != s.end(); p++)
if (a[i].first < p->first and a[i].second > p->first)
{
num++;
if (num > n - 1 or !merge(i, p->second))
{
cout << "NO";
return 0;
}
}
else
break;
s.insert(make_pair(a[i].second, i));
}
if (num < n - 1)
cout << "NO";
else
cout << "YES";
}