1.题目描述:
n个人,m对关系,关系具有传递性,给你m个描述,问你这样的图是否符合关系图
3.解题思路:
关系具有传递性,很容易想到用并查集来维护。主要是怎么处理关系图矛盾。观察到,正常关系图,每点的度即为他和别人的关系,如果他在一棵树里面,则他的度应该等于 这棵树的节点总数-1(这个很容易理解,你的朋友圈为n人(包括你自己),那么你就有n-1对关系),那么我们在连边的时候处理同时一下他们的度就好了。
4.AC代码:
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define maxn 150150
#define N 1111
#define eps 1e-6
#define pi acos(-1.0)
#define e exp(1.0)
using namespace std;
const int mod = 1e9 + 7;
typedef long long ll;
typedef unsigned long long ull;
int pa[maxn], r[maxn], cnt[maxn];
void init(int n)
{
for (int i = 1; i <= n; i++)
{
pa[i] = i;
r[i] = 0;
cnt[i] = 0;
}
}
int findset(int x)
{
if (x == pa[x])
return x;
return pa[x] = findset(pa[x]);
}
void unionset(int a, int b)
{
int a1 = findset(a);
int b1 = findset(b);
if (a1 != b1)
pa[a1] = b1;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
long _begin_time = clock();
#endif
int n, m;
while (~scanf("%d%d", &n, &m))
{
init(n);
while (m--)
{
int u, v;
scanf("%d%d", &u, &v);
cnt[u]++; //记录每个节点的度
cnt[v]++;
unionset(u, v);
}
for (int i = 1; i <= n; i++)
r[findset(i)]++; //根节点的秩统计这棵树上有多少元素
int flag = 1;
for (int i = 1; i <= n; i++)
{
int root = findset(i);
if (cnt[i] != r[root] - 1)
{
flag = 0;
break;
}
}
if (flag)
puts("YES");
else
puts("NO");
}
#ifndef ONLINE_JUDGE
long _end_time = clock();
printf("time = %ld ms.", _end_time - _begin_time);
#endif
return 0;
}