WA on #67 求调
查看原帖
WA on #67 求调
325995
Zxd2009楼主2024/7/13 18:29
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;

struct Edge
{
	int x, y;
};
Edge b[400005];

bool cmp1(Edge x, Edge y)
{
	if(x.x != y.x)  return x.x < y.x;
	return x.y < y.y;
}

int n, m, x, y, cnt, maxn = 1, l[400005], a[200005], fa[200005];
bool flag[200005];

int fnd(int x)
{
	if(x == fa[x])  return x;
	return fa[x] = fnd(fa[x]);
}
inline void findEdge(int x)
{
	int cur = 1;
	for(int i = l[x]; i < l[x + 1]; i++)
	{
		while(cur < b[i].y)
		{
			fa[fnd(cur)] = fnd(x);
			flag[cur] = true;
			cur++;
		}
		cur++;
	}
	while(cur <= n)
	{
		fa[fnd(cur)] = fnd(x);
		flag[cur] = true;
		cur++;
	}
}

int main()
{
	scanf("%d%d", &n, &m);
	for(int i = 1; i <= m; i++)
	{
		scanf("%d%d", &b[i].x, &b[i].y);
		b[i + m].x = b[i].y;
		b[i + m].y = b[i].x;
	}
	m *= 2;
	sort(b + 1, b + m + 1, cmp1);
	for(int i = 1; i <= m; i++)
	{
		if(b[i].x != b[i - 1].x)
		{
			for(int j = b[i - 1].x + 1; j <= b[i].x; j++)  l[j] = i;
		}
	}
	for(int j = b[m].x + 1; j <= n + 1; j++)  l[j] = m + 1;
	
	for(int i = 1; i <= n; i++)
	{
		fa[i] = i;
		if(l[i + 1] - l[i] < l[maxn + 1] - l[maxn])  maxn = i;
	}
	findEdge(maxn);
	for(int i = 1; i <= n; i++)
	{
		if(!flag[i])  findEdge(i);
	}
	
	for(int i = 1; i <= n; i++)
	{
		if(a[fnd(i)] == 0)  cnt++;
		a[fnd(i)]++;
	}
	sort(a + 1, a + n + 1);
	printf("%d\n", cnt);
	for(int i = 1; i <= n; i++)
	{
		if(a[i] != 0)  printf("%d ", a[i]);
	}
	return 0;
}

b 是存边的数组,l 是每个点在 b 数组中存放的起始位置,findEdge 是找一个点连接的所有边并且放入并查集,flag 是这个点有没有被放到并查集中。

2024/7/13 18:29
加载中...