Loading

【题解】[POI 2019] Układ scalony

给定一个 \(n\times m\) 的网格图,生成一颗直径为 \(k\) 的树。

首先不难得到一个粗略的上下界。直径不可能超过 \(n\times m -1\) ,不可能小于 \(n+m-2\)

但是手算一下 \(2\times 2\)\(2\times 4\) 之类的网格,发现也无法构造出直径为 \(n+m-2\) 的树。

对于 \(n,m\) 中有一个为奇数的情况,我们可以找出中间行/列,其余所有点向中间行/列方向连边,可以得到一颗直径为 \(n+m-2\) 的树,同时这也是下界。

对于 \(n,m\) 都是偶数,取 \(\left\lfloor\dfrac{n}{2}\right\rfloor\) 行为中间行,其余点向中间行方向连边,可以得到一颗直径为 \(n+m-1\) 的树,同时这也是下界。

对于 \(n,m\) 中有一个奇数的情况,我们取 \((1,1)\)\((n,m)\) 为直径的两端,每次从两端向外扩展一格,可以得到所有直径长度在 \([n+m-2,n\times m-1]\) 之间的树。

对于 \(n,m\) 均为偶数的情况,我们将 \((1,1)\)\((1,2)\) 连边,发现直径仍然是 \(n+m-1\) ,然后以 \((1,2)\)\((n,m)\) 为直径的两端,每次向外扩展一格,可以得到所有直径长度在 \([n+m-1,n\times m-1]\) 之间的树。

但是当 \(n=2\)\((1,1)\)\((1,2)\) 同时属于中间行,这种构造方法行不通。

我们稍作修改,\(n=2\)\(m!=2\) 时,我们可以交换 \(n,m\) 使之成为 \(n!=2\) 的情况。而 \(n=m=2\) 时,只有 \(k=3\) 时有解,特判一下即可。

时间复杂度 \(\mathcal{O}(nm)\)

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define pre(i,a,b) for(int i=a;i>=b;i--)
#define N 1005
using namespace std;
int n,m,k,op,v[N][N];
namespace task1{
	typedef pair<int,int> Pr;
	#define F first
	#define S second
	vector<pair<Pr,Pr> >a;
	void ins(int x,int y,int p,int q){
		a.push_back(make_pair(make_pair(x,y),make_pair(p,q)));
	}
	void main(){
		if(k<n+m-2||k>=n*m){puts("NIE");return ;}
		puts("TAK");
		int cen=(n+1)/2;
		rep(i,1,m-1)ins(cen,i,cen,i+1);
		rep(i,1,cen-1)ins(i,1,i+1,1),v[i][1]=1;
		rep(i,cen+1,n)ins(i,m,i-1,m),v[i][m]=1;
		int x=1,y=1,tp=0;k-=n+m-2;int w=min(k,(cen-1)*(m-1));
		rep(i,1,w){
			k--;
			if(tp==0&&y==m)ins(x,y,x+1,y),tp=1,x++;
			else if(tp==1&&y==2)ins(x,y,x+1,y),tp=0,x++;
			else if(tp==0)ins(x,y,x,y+1),y++;
			else ins(x,y,x,y-1),y--;
			v[x][y]=1;
		}
		rep(i,1,m)v[cen][i]=1;
		x=n,y=m,tp=0;w=min(k,(cen-1)*(m-1));
		rep(i,1,w){
			k--;
			if(tp==0&&y==1)ins(x,y,x-1,y),tp=1,x--;
			else if(tp==1&&y==m-1)ins(x,y,x-1,y),tp=0,x--;
			else if(tp==0)ins(x,y,x,y-1),y--;
			else ins(x,y,x,y+1),y++;
			v[x][y]=1;
		}
		rep(i,1,n)rep(j,1,m)if(!v[i][j]){
			if(i>cen)ins(i,j,i-1,j);
			else ins(i,j,i+1,j);
		}
		rep(i,0,n*m-2){
			if(op)printf("%d %d %d %d\n",a[i].F.S,a[i].F.F,a[i].S.S,a[i].S.F);
			else printf("%d %d %d %d\n",a[i].F.F,a[i].F.S,a[i].S.F,a[i].S.S);
		}
	}
}
namespace task2{
	typedef pair<int,int> Pr;
	#define F first
	#define S second
	vector<pair<Pr,Pr> >a;
	void ins(int x,int y,int p,int q){
		a.push_back(make_pair(make_pair(x,y),make_pair(p,q)));
	}
	void main(){
		if(n==2&&m==2){
			if(k!=3){puts("NIE");return;}
			printf("TAK\n1 1 1 2\n1 1 2 1\n2 2 1 2\n");
			return ;
		}
		if(n<m)swap(n,m),op^=1;
		if(k<n+m-1||k>=n*m){puts("NIE");return ;}
		puts("TAK");
		int cen=n/2;
		rep(i,1,m)v[cen][i]=1;
		rep(i,1,m-1)ins(cen,i,cen,i+1);
		rep(i,1,cen-1)ins(i,1,i+1,1),v[i][1]=1;
		rep(i,cen+1,n)ins(i,m,i-1,m),v[i][m]=1;
		v[1][2]=1;ins(1,1,1,2);
		int x=1,y=2,tp=0;k-=n+m-1;int w=min(k,(cen-1)*(m-1)-1);
		rep(i,1,w){
			k--;
			if(tp==0&&y==m)ins(x,y,x+1,y),tp=1,x++;
			else if(tp==1&&y==2)ins(x,y,x+1,y),tp=0,x++;
			else if(tp==0)ins(x,y,x,y+1),y++;
			else ins(x,y,x,y-1),y--;
			v[x][y]=1;
		}
		x=n,y=m,tp=0;w=min(k,cen*(m-1));
		rep(i,1,w){
			k--;
			if(tp==0&&y==1)ins(x,y,x-1,y),tp=1,x--;
			else if(tp==1&&y==m-1)ins(x,y,x-1,y),tp=0,x--;
			else if(tp==0)ins(x,y,x,y-1),y--;
			else ins(x,y,x,y+1),y++;
			v[x][y]=1;
		}
		rep(i,1,n)rep(j,1,m)if(!v[i][j]){
			if(i>cen)ins(i,j,i-1,j);
			else ins(i,j,i+1,j);
		}
		rep(i,0,n*m-2){
			if(op)printf("%d %d %d %d\n",a[i].F.S,a[i].F.F,a[i].S.S,a[i].S.F);
			else printf("%d %d %d %d\n",a[i].F.F,a[i].F.S,a[i].S.F,a[i].S.S);
		}
	}
}
int main(){
	scanf("%d%d%d",&n,&m,&k);
	if(m&1)swap(n,m),op=1;
	if(n&1)task1::main();
	else task2::main();
	return 0;
}
posted @ 2021-06-07 16:25  7KByte  阅读(101)  评论(0编辑  收藏  举报