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;
}
posted @ 2025-09-12 19:39  FormulaOne  阅读(10)  评论(0)    收藏  举报