题解 构造题

传送门

出题人精心构造数据使得 \(O(4^n)\) 能够通过,离谱

有一个并不知道是如何想到的做法:
将所有点按坐标排序,右到左,上到下枚举点染色
发现这样染到一个点时与其相邻的以染色的点不超过 4 个
按顺时针编号 \(p_0\cdots p_3\)
尝试将该点颜色染为 \(col_{p_0}\)\(p_0\) 颜色改为 \(p_2\)
于是从 \(p_0\) BFS 找需要改颜色的点,若搜到了 \(p_2\) 则不合法,换 \(p_1, p_3\)
这里选点的方案本来是任意的,但这样交错选的话若 2,4 不合法可以直接将合法方案定位到 1, 3
于是复杂度是 \(O(m^2)\)

点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#define fir first
#define sec second
#define pb push_back
#define ll long long
//#define int long long

char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
	int ans=0, f=1; char c=getchar();
	while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
	while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
	return ans*f;
}

int n, m, k;
vector<int> e[N];
bool vis[N], inq[N];
pair<int, int> a[N], b[N];
map<pair<int, int>, int> mp1, mp2;
int col[N], p[N], lkp[N], q[N], l, r;

bool bfs(int lim, int s, int t, int c) {
	q[l=r=1]=s; inq[s]=1;
	while (l<=r) {
		int u=q[l++];
		for (auto v:e[u])
			if (v>=lim && !inq[v] && col[v]==c-col[u]) inq[q[++r]=v]=1;
	}
	if (inq[t]) {
		while (r) inq[q[r--]]=0;
		return 0;
	}
	while (r) {
		int u=q[r--];
		col[u]=c-col[u]; inq[u]=0;
	}
	return 1;
}

signed main()
{
	freopen("construct.in", "r", stdin);
	freopen("construct.out", "w", stdout);

	n=read(); m=read(); k=read();
	for (int i=1; i<=n; ++i) a[i].fir=read(), a[i].sec=read(), mp1[a[i]]=i, b[i]=a[i];
	sort(a+1, a+n+1);
	for (int i=1; i<=n; ++i) mp2[a[i]]=i;
	for (int i=1,u,v; i<=m; ++i) {
		u=mp2[b[read()]]; v=mp2[b[read()]];
		e[u].pb(v); e[v].pb(u);
	}
	for (int i=n; i; --i) {
		for (int j=1; j<=4; ++j) vis[j]=0;
		for (auto v:e[i]) vis[col[v]]=1;
		for (int j=1; j<=4; ++j) if (!vis[j]) {col[i]=j; break;}
		if (col[i]) continue;
		for (auto v:e[i]) if (col[v]) {
			if (a[v].fir==a[i].fir) p[0]=v;
			else if (a[v].sec>a[i].sec) p[1]=v;
			else if (a[v].sec==a[i].sec) p[2]=v;
			else p[3]=v;
		}
		col[i]=col[p[0]];
		if (!bfs(i+1, p[0], p[2], col[p[0]]+col[p[2]])) col[i]=col[p[1]], bfs(i+1, p[1], p[3], col[p[1]]+col[p[3]]);
	}
	for (int i=1; i<=n; ++i) lkp[mp1[a[i]]]=i;
	for (int i=1; i<=n; ++i) printf("%d\n", col[lkp[i]]);
	
	return 0;
}
posted @ 2022-02-16 20:23  Administrator-09  阅读(1)  评论(0编辑  收藏  举报