1. 程式人生 > >CF 518C Colored Rooks 構造

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;
}