Grayscale Confusion “范式杯”2023牛客暑期多校训练营10 L

10 篇文章 0 订阅

登录—专业IT笔试面试备考平台_牛客网

题目大意:有n个三维三维向量,c[i]=(x,y,z),定义c[i]<c[j]当且仅当c[i].x<c[j].x&&c[i].y<c[j].y&&c[i].z<c[j].z,现要求给每一个c[i]赋值一个数w[i],使w[i]的大小能够反映c[i]之间的大小关系,求满足w[1]=w[2],问有无合法的w[i],有则输出一种方案

2<=n<=1000;0<=x[i],y[i],z[i]<=255

思路:考虑从满足c[i]<c[j]的i和j 之间建立映射关系,可以发现,如果有多个i,满足c[i]<c[j],那么w[j],应该等于所有满足关系的w[i]的最大值再+1,也就是如果从最小的点开始bfs,当子节点的所有父结点的w都求出来后再更新子节点的w。

那么就变成了类似于求拓扑序的过程,求出每个点的入度,初始将所有最小的也就是入度为0的点放入队列,每访问一个点就令其入度-1,同时更新ans[v]=max(ans[v],ans[u]+1),入度为0后放入队列

考虑w[1]和w[2]应该相等的问题,如果c[1]c[2]之间是有明确的大小关系的,那么显然不合法,如果合法的话,我我们就将他们的w[i]统一成最大的那一个,这样原先比他们小的依然是符合条件的,但比他们大的有可能不符合条件,所以需要再跑一遍拓扑排序,得到的新的答案一定是符合所有映射关系的

#include<bits/stdc++.h>
//#include<__msvc_all_public_headers.hpp>
using namespace std;
typedef long long ll;
const int N = 1e3 + 10;
int n;
int ans[N];
int in[N];
vector<int>g[N];
int in2[N];
void init()
{
	for (int i = 1; i <= n; i++)
	{
		in[i] = 0;
		g[i].clear();
		ans[i] = 0;
		in2[2] = 0;
	}
}
struct node
{
	int r, g, b;
	node(int a, int d, int c)
	{
		r = a, g = d, b = c;
	}
	node()
	{

	}
}a[N];
void solve()
{
	cin >> n;
	init();
	for (int i = 1; i <= n; i++)
	{
		int r, g, b;
		cin >> r >> g >> b;
		a[i] = { r, g, b };
	}
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= n; j++)
		{
			if (a[i].r < a[j].r && a[i].g < a[j].g && a[i].b < a[j].b)
			{//有明确大小关系的建立映射关系
				in[j]++;
				in2[j]++;//因为要求两遍拓扑,所以建一个备用
				g[i].push_back(j);
			}
		}
	}
	queue<int>q;
	for (int i = 1; i <= n; i++)
	{
		if (!in[i])
		{//入度为0的点入队
			q.push(i);
		}
	}
	while (!q.empty())
	{
		int u = q.front();
		q.pop();		
		for (int i = 0; i < g[u].size(); i++)
		{
			int v = g[u][i];
			in[v]--;
            ans[v] = max(ans[v],ans[u]+1);//子节点是父结点w的最大值
			if(!in[v])
				q.push(v);//入度为0入队
		}
	}
	if (!(a[1].r < a[2].r && a[1].g < a[2].g && a[1].b < a[2].b) && !(a[1].r > a[2].r && a[1].g > a[2].g && a[1].b > a[2].b))
	{//c[1]c[2]是合法的
		for (int i = 1; i <= n; i++)
		{
			in[i] = in2[i];
		}
		ans[1] = max(ans[1], ans[2]);
        ans[2] = max(ans[1], ans[2]);//两者w[i]取最大值再跑一遍拓扑
		for (int i = 1; i <= n; i++)
		{
			if (!in[i])
			{				
					q.push(i);
			}
		}
		while (!q.empty())
		{
			int u = q.front();
			q.pop();
			for (int i = 0; i < g[u].size(); i++)
			{
				int v = g[u][i];
				ans[v] = max(ans[v], ans[u] + 1);
				in[v]--;
				if (!in[v])
					q.push(v);
			}
		}
	}	
	else
	{
		cout << -1 << endl;
		return;
	}
	for (int i = 1; i <= n; i++)
	{
		cout << ans[i] << endl;
	}
}
int main()
{
	cin.tie(0);
	cout.tie(0);
	ios::sync_with_stdio(false);
	int t;
	t=1;
	while (t--)
	{
		solve();
	}
	return 0;
}

//7
//3 3 3
//3 1 1
//0 0 0
//1 1 2
//1 1 2
//4 2 2
//5 4 4
//6
//3 3 3
//3 0 1
//0 0 0
//1 1 2
//1 1 2
//4 1 2
//6
//3 3 3
//3 1 1
//0 0 0
//1 1 2
//1 1 2
//4 1 2
//5
//3 3 3
//3 0 1
//0 0 0
//1 1 2
//1 1 2
//
//6
//0 0 0
//0 1 2
//1 1 1
//2 2 2
//2 3 2
//3 3 3
//
//3
//0 0 0
//2 2 2
//1 1 1
//
//3
//1 0 0
//0 1 0
//0 0 1
//
//3
//0 0 0
//0 1 2
//255 255 255

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

timidcatt

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值