竞赛讨论区 > J题-7.5%正确(WA)-样例过
头像
lxy_qwq
编辑于 2025-02-08 17:22 江西
+ 关注

J题-7.5%正确(WA)-样例过

题面:

#include <iostream>
#include <queue>
#include <climits>
using namespace std;
int n, m, t, cnt, num;
int k;
const int MAXN = 2e5 + 5;
int head[MAXN];
int cnm[MAXN];//注:用于存储每一个数的位置
//由于可能会出现bug,那么就要
struct Node {
	int to, next;
}e[MAXN];
void add(int x, int y)
{
	e[cnt].next = head[x];
	e[cnt].to = y;
	head[x] = cnt++;
}
bool vis[MAXN];
bool cnmt[MAXN];//记录这一个数字有没有输出
struct nnode {
	int v;//记录你的值
	int ssum;//记录批次
	friend bool operator<(nnode a, nnode b)
	{
		if (a.ssum == b.ssum)
		{
			return a.v > b.v;
		}
		return a.ssum > b.ssum;
	}
};
struct node {
	int xb;//有多少元素
	int zuix;
	priority_queue<nnode> a;//考虑批次,同一批次的选择最小的,知道xuanwanoperat
	friend bool operator <(node a, node b)
	{
		if (a.xb == b.xb)
		{
			return a.zuix > b.zuix;
		}
		return a.xb < b.xb;//元素多的靠前
	}
}from[MAXN];
priority_queue<node> q;//求出来
void init(int len)
{
	for (int i = 0; i < len; i++)
	{
		head[i] = -1;
		cnm[i] = INT_MAX;
		cnmt[i] = 0;
		vis[i] = 0;
		from[i].xb = 0;
		while (!from[i].a.empty())
		{
			from[i].a.pop();
		}
	}
	cnt = 0;
	num = 0;
}
void BFS(int i, bool z)
{
	//求出连通块
	int ni = 1;//你的批次
	queue<int> xt;
	vis[i] = 1;
	xt.push(i);
	from[num].zuix = INT_MAX;//初始化
	while (!xt.empty())
	{
		int sz = xt.size();
		while (sz--)
		{
			int now = xt.front();
			xt.pop();
			cnm[now] = min(ni, cnm[now]);
			//std::cout << "在第" << num << "个连通块的第" << ni << "层找到了" << now << endl;
			from[num].xb++;
			from[num].a.push({ now , ni });
			from[num].zuix = min(from[num].zuix, now);
			for (int i = head[now]; ~i; i = e[i].next)
			{
				int v = e[i].to;
				//std::cout << v << endl;
				if (vis[v] == z)
				{
					vis[v] = 1 - z;
					xt.push(v);
				}
			}
		}
		ni++;
	}
}

int main()
{
	//需要分类讨论
	cin >> t;
	while (t--)
	{
		while (!q.empty())
		{
			q.pop();
		}
		/*
		5 4 1
		1 2
		2 3
		3 1
		4 5

		*/
		cin >> n >> m >> k;
		init(n + 1);//已经初始化了
		num = 1;

		while (m--)
		{
			int xx, y;
			cin >> xx >> y;
			add(xx, y);
			add(y, xx);
		}

		for (int i = 1; i <= n; i++)
		{
			if (vis[i] == 0)
			{
				BFS(i, 0);
				num++;//更新标记
			}
		}
		//num >= k表示图走不
		num--;
		//std::cout << "当前有" << num << "个连通块" << endl;
		if (num >= k)
		{
			//刚好走完整一个图
			//选择几个最大的,然后扔进去排序
			for (int i = 1; i <= num; i++)
			{
				//把所有已经测试过的放进去
				q.push(from[i]);//放进去了所有的
				from[i].xb = 0;
			}
			//接下来,选择前面k个
			//有num-1个连通块,就相当于我们希望可以让值越小越好
			node zong;
			zong.xb = 0;
			while (k--)
			{
				node now = q.top();//已经找到了这些东西
				while (!now.a.empty())
				{
					//把这些都放进去
					//std::cout << "可到达" << now.a.top().v << endl;//你可以到达的点
					zong.a.push(now.a.top());
					zong.xb++;//增加数量
					now.a.pop();
				}
				q.pop();
			}
			std::cout << zong.xb << endl;
			while (!zong.a.empty())
			{
				std::cout << zong.a.top().v << " ";

				zong.a.pop();
			}
			cout << endl;
		}
		else
		{
			//还有多余次数
			for (int i = 1; i <= n; i++)
			{
				//std::cout << i << " " << cnm[i] << endl;
				if (cnm[i] > i)
				{
					//你不是可以的
					//std::cout << i << "可以进一步优化" << endl;
					BFS(i, vis[i]);
					num++;//更新标记
				}
			}

			//把剩下的放进去
			for (int i = 1; i <= num; i++)
			{
				//把所有已经测试过的放进去
				q.push(from[i]);
			}
			//判断能不能取
			//接下来,选择前面k个
			//有num-1个连通块,就相当于我们希望可以让值越小越好
			node zong;
			zong.xb = 0;
			while (k--)
			{
				//cout << "k = " << k << endl;
				node now = q.top();//已经找到了这些东西
				while (!now.a.empty())
				{
					//把这些都放进去
					//cout << "还有" << now.a.size() << "个元素" << endl;
					if (cnmt[now.a.top().v] == 1)
					{
						now.a.pop();
						//已经来过了
						continue;
					}
					cnmt[now.a.top().v] = 1;
					//std::cout << "可到达" << now.a.top().v << endl;//你可以到达的点
					zong.a.push(now.a.top());
					zong.xb++;//增加数量
					now.a.pop();
				}
				q.pop();
				if (q.empty())
				{
					//为空
					break;
				}
			}
			std::cout << zong.xb << endl;
			while (!zong.a.empty())
			{
				std::cout << zong.a.top().v << " ";

				zong.a.pop();
			}
			cout << endl;
		}
	}
	return 0;
}

全部评论

(0) 回帖
加载中...
话题 回帖

等你来战

查看全部

热门推荐