题意: [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;
}