CF 518C Colored Rooks 構造
阿新 • • 發佈:2018-11-01
題意: [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; }