HDU7074 Little prince and the garden of roses
首先可以对于每一个颜色分别考虑。
如果存在与\((i,j)\),就在\(i,j+n\)中间连一条边。
形成一个二分图。
你需要给每一个二分图染色,使得颜色相同的边不能公用一个顶点。
有一个经典结论,颜色数即为最大度数。
首先这个很显然可以网络流,每次找一个最大匹配,但是这样复杂度是\(O(N^3\sqrt N)\)的,会\(TLE\)。
考虑一种调整方法。
首先一条边一条边考虑。
假设当前需要将边\((u,v)\)染色。
如果\(u,v\)都不含有颜色\(x\),则将\((u,v)\)染成\(x\)。
否则找到一个\(u\)不含有的颜色\(x\),\(v\)不含有的颜色\(y\)。
将\((u,v)\)染成\(x\)。
然后需要将\(v\)原来连着的\(x\)改成\(y\)。
然后一路调整下去。
可以发现这条链是无环的。
所以时间复杂度是\(O(N^3)\)。
#include<bits/stdc++.h>
#define rb(a,b,c) for(int a=b;a<=c;++a)
#define rl(a,b,c) for(int a=b;a>=c;--a)
#define LL long long
#define IT iterator
#define PB push_back
#define II(a,b) make_pair(a,b)
#define FIR first
#define SEC second
#define FREO freopen("check.out","w",stdout)
#define rep(a,b) for(int a=0;a<b;++a)
#define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define random(a) rng()%a
#define ALL(a) a.begin(),a.end()
#define POB pop_back
#define ff fflush(stdout)
#define fastio ios::sync_with_stdio(false)
#define check_min(a,b) a=min(a,b)
#define check_max(a,b) a=max(a,b)
using namespace std;
//inline int read(){
// int x=0;
// char ch=getchar();
// while(ch<'0'||ch>'9'){
// ch=getchar();
// }
// while(ch>='0'&&ch<='9'){
// x=(x<<1)+(x<<3)+(ch^48);
// ch=getchar();
// }
// return x;
//}
const int INF=0x3f3f3f3f;
typedef pair<int,int> mp;
/*}
*/
const int MAXN=3e2+1;
int n,c[MAXN][MAXN];
vector<mp> pos[MAXN*MAXN];
int pt[MAXN*2][MAXN];
int deg[MAXN*2];
vector<pair<mp,int> > path;
void modify(int now,int x,int y){//x->y
if(pt[now][x]==-1){
return ;
}
path.PB(II(II(pt[now][x],now),y));
int nx=pt[now][x];
pt[now][x]=-1;
pt[nx][x]=-1;
modify(nx,y,x);
}
void solve(){
scanf("%d",&n);
rb(i,1,n) rb(j,1,n) scanf("%d",&c[i][j]);
rb(i,1,n*n) pos[i].clear();
rb(i,1,n) rb(j,1,n) pos[c[i][j]].PB(II(i,j));
int answer1=0;
vector<pair<mp,int > > answer2;
rb(i,1,n*n){
if(pos[i].size()==0) continue;
rb(j,1,n*2) deg[j]=0;
int D=0;
vector<mp> edges;
for(auto it:pos[i]){
edges.PB(II(it.FIR,it.SEC+n));
deg[it.FIR]++;
deg[it.SEC+n]++;
}
D=*max_element(deg+1,deg+1+n+n);
check_max(answer1,D-1);
if(D==1) continue;
rep(k,D){
rb(j,1,n*2) pt[j][k]=-1;
}
for(auto it_:edges){
int u,v;
u=it_.FIR;
v=it_.SEC;
// cout<<u<<' '<<v<<endl;
int ok=-1;
rep(k,D){
if(pt[u][k]==-1&&pt[v][k]==-1){
ok=k;
break;
}
}
if(ok!=-1){
pt[u][ok]=v;
pt[v][ok]=u;
continue;
}
int x,y;
rep(k,D){
if(pt[u][k]==-1){
x=k;
}
if(pt[v][k]==-1){
y=k;
}
}
path.clear();
modify(v,x,y);
pt[u][x]=v;
pt[v][x]=u;
for(auto it:path){
pt[it.FIR.FIR][it.SEC]=it.FIR.SEC;
pt[it.FIR.SEC][it.SEC]=it.FIR.FIR;
}
}
rb(i,1,n){
rep(k,D){
if(k&&pt[i][k]!=-1){
answer2.PB(II(II(i,pt[i][k]-n),k));
}
}
}
}
printf("%d %d\n",answer1,(int)(answer2.size()));
for(auto it:answer2){
printf("%d %d %d\n",it.FIR.FIR,it.FIR.SEC,it.SEC);
}
}
int main(){
int T;
scanf("%d",&T);
while(T--) solve();
return 0;
}