CF 518C Colored Rooks 构造

题意: [1:n]n种颜色,m个加成(a,b) 表示颜色a,b为和谐的. 

1e9*1e9的网格,每个棋子可以到它同行或者同列的某个棋子上.

要求选出摆放k个棋子满足以下要求  k只需要<=5000.

要求1: 每种颜色的棋子个数>=1.

要求2: 同一种颜色的棋子是联通的.

要求3:两个不同颜色的棋子a,b. 只要当(a,b)出现在m个加成中时,(a,b)棋子构成的集合时联通的.

n<=100. m<=min(1000,n*(n-1)/2).  保证一定有解,输出每种颜色的棋子数量和位置.

先构造相同颜色联通,不同颜色不联通的情况.

第1种颜色一个在(1,1), 第二种颜色放一个在(1+n,2+n). 第i种颜色放一个在(1+(i-1)*n,2+(i-1)*n)上.

令r[i],c[i]为初始颜色i的行和列. 若存在加成(i,j)  那么(r[i],c[j]+i)放置颜色i, (r[j],c[j]+i)放置颜色j  .  

颜色(i,j)联通,每行都只有一种颜色,并且从列角度去看.一列最多两种颜色棋子.

标程构造: n种颜色每种先放一个在(i,i) 对于m个加成.每次选空的一列j,放上(a,j),(b,j)即可.[每行一种颜色.每列最多两种颜色]


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> ii;
const int N=2e4+5;
int n,m,r[N],c[N];
vector<ii> res[N];
map<ii,int> a;
int main(){
	ios::sync_with_stdio(false);cin.tie(0);
	cin>>n>>m;
	for(int i=1;i<=n;i++)	r[i]=(i-1)*n+1,c[i]=(i-1)*n+1,a[ii(r[i],c[i])]=i;
	for(int k=1;k<=m;k++){
		int x,y;
		cin>>x>>y;
		if(x>y)	swap(x,y);
		a[ii(r[x],c[y]+x)]=x;
		a[ii(r[y],c[y]+x)]=y;
	}
	for(auto it=a.begin();it!=a.end();it++){
		int c=it->second;
		res[c].push_back(it->first);
	}
	for(int i=1;i<=n;i++){
		int sz=int(res[i].size());
		printf("%d\n",sz);
		for(int j=0;j<sz;j++)	printf("%d %d\n",res[i][j].first,res[i][j].second);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/noone0/article/details/83378264
今日推荐