ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

NOI 2016 题目选做

2022-04-30 11:34:21  阅读:159  来源: 互联网

标签:选做 NOI int tt read include && 2016 跳蚤


网格

题目描述

点此看题

解法

首先有一个关键的 \(\tt observation\):答案不会超过 \(2\)(可以直接封锁边界点),那么根据众多 \(\tt CF\) 题目的经验,我们可以直接开始分类讨论:

  • 如果只剩一个跳蚤,或者只剩两个跳蚤并且它们联通,那么答案是 -1
  • 如果已经存在两个跳蚤不连通,那么答案是 0
  • 把相邻的跳蚤连边,如果原图存在割点那么答案是 1
  • 否则答案是 2

那么暴力建图可以做到 \(O(nm)\) 的复杂度,一个比较显然的思路是保留每个障碍旁边的若干点,虽然貌似这种做法可以通过官方数据但是很容易被 \(\tt hack\),这里介绍一种不需要特判的优化建图方法,首先我们保留这些点:

  • 距离四个角 \(2\times 2\) 范围内的点。
  • 和某个障碍物八联通的点。
  • 和某个障碍物在同一行\(/\)列,并且自己身处边界的点。

那么对于保留的点,如果两个点在同一行或者同一列并且中间没有障碍物,就连一条边。最后暴力 \(\tt tarjan\) 求割点即可,时间复杂度 \(O(c)\)

正确性证明待补充。

#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
const int M = 10000005;
#define pb push_back
int read()
{
	int x=0,f=1;char c;
	while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
	while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
	return x*f;
}
int T,n,m,c,q,t,cnt,zxy,dfn[M],low[M];
vector<int> g[M];
struct node {int x,y,t;}a[M];
bool cmp1(node a,node b)
{
	if(a.x==b.x && a.y==b.y) return a.t<b.t;
	if(a.x==b.x) return a.y<b.y;
	return a.x<b.x;
}
bool cmp2(node a,node b)
{
	return a.y==b.y?a.x<b.x:a.y<b.y;
}
void add(int x,int y,int dx,int dy)
{
	for(int i=-dx;i<=dx;i++)
		for(int j=-dy;j<=dy;j++)
		{
			int tx=x+i,ty=y+j;
			if(tx>=1 && tx<=n && ty>=1 && ty<=m)
				a[++t]={tx,ty,0};
		}
}
void dfs(int u,int fa)
{
	dfn[u]=low[u]=++cnt;int son=0;
	for(int v:g[u])
	{
		if(!dfn[v])
		{
			dfs(v,u);
			low[u]=min(low[u],low[v]);
			if(low[v]>=dfn[u])
			{
				if(fa) zxy=1;
				else son++;
			}
		}
		else if(v!=fa) low[u]=min(low[u],dfn[v]); 
	}
	if(son>1) zxy=1;
}
void work()
{
	n=read();m=read();c=read();q=t=0;
	for(int i=1;i<=c;i++)
	{
		int x=read(),y=read();
		add(x,y,1,1);
		add(1,y,0,0);add(n,y,0,0);
		add(x,1,0,0);add(x,m,0,0);
		a[++t]={x,y,-1};
	}
	add(1,1,2,2);add(1,m,2,2);add(n,1,2,2);add(n,m,2,2);
	sort(a+1,a+1+t,cmp1);int pt=0;node ls;
	for(int i=1;i<=t;i++)
		if(ls.x!=a[i].x || ls.y!=a[i].y)
			ls=a[i],a[++pt]=ls;
	t=pt;cnt=zxy=0;
	for(int i=1;i<=t;i++)
		if(a[i].t!=-1) a[i].t=++q;
	for(int i=1;i<=q;i++)
		dfn[i]=low[i]=0,g[i].clear();
	for(int i=2;i<=t;i++)
		if(a[i].x==a[i-1].x && a[i].t!=-1 && a[i-1].t!=-1)
			g[a[i].t].pb(a[i-1].t),g[a[i-1].t].pb(a[i].t);
	sort(a+1,a+1+t,cmp2);
	for(int i=2;i<=t;i++)
		if(a[i].y==a[i-1].y && a[i].t!=-1 && a[i-1].t!=-1)
			g[a[i].t].pb(a[i-1].t),g[a[i-1].t].pb(a[i].t);
	if(q<=1 || (q<=2 && !g[1].empty()))
	{
		puts("-1");
		return ;
	}
	dfs(1,0);
	if(cnt<q) puts("0");
	else puts(zxy?"1":"2");
}
signed main()
{
	T=read();
	while(T--) work();
}

标签:选做,NOI,int,tt,read,include,&&,2016,跳蚤
来源: https://www.cnblogs.com/C202044zxy/p/16209723.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有