CF1774D
首先 \(1\) 的总个数不能被 \(n\) 整除时无解。
否则一定有解(因为每一列上的 \(1\) 的位置都可以随意变动,故实际上相当于可以随便放)。为了步数最少,一定是用缺少 \(1\) 行的 \(0\) 与过多 \(1\) 行的 \(1\) 交换,这样能同时使两行更接近答案。实现时先枚举列,再根据每行的情况找出上面两种行,并一一配对交换即可。时间复杂度 \(O(\sum nm)\)。
#include<iostream>
#include<cstdio>
#include<vector>
#define N 200010
using namespace std;
int n,m,cnt[N],cnt0;
vector<int> G[N],a,b;
int ans,ansx[N*10],ansy[N*10],ansz[N*10];
void solve(){
cnt0=0;
cin>>n>>m;
for(int i=1;i<=n;i++)
G[i].clear();
for(int i=1;i<=n;i++){
G[i].push_back(0);
cnt[i]=0;
for(int j=1;j<=m;j++){
G[i].push_back(0);
cin>>G[i][j];
cnt0+=G[i][j];
cnt[i]+=G[i][j];
}
}
if(cnt0%n){
cout<<-1<<'\n';
return;
}
cnt0/=n;
ans=0;
for(int j=1;j<=m;j++){
a.clear();b.clear();
for(int i=1;i<=n;i++){
if(cnt[i]<cnt0&&!G[i][j])a.push_back(i);
if(cnt[i]>cnt0&&G[i][j])b.push_back(i);
}
for(int i=0;i<min(a.size(),b.size());i++){
ans++;
ansx[ans]=a[i],ansy[ans]=b[i],ansz[ans]=j;
cnt[a[i]]++,cnt[b[i]]--;
}
}
cout<<ans<<'\n';
for(int i=1;i<=ans;i++)
cout<<ansx[i]<<' '<<ansy[i]<<' '<<ansz[i]<<'\n';
return;
}
int main(){
int T;
cin>>T;
while(T--)
solve();
return 0;
}

浙公网安备 33010602011771号