Cordforces 1774D題解
題目鏈接: https://codeforces.com/problemset/problem/1774/D
Description:
給定n個長為m的二進制串,每次可以選出任意兩個,然后交換這兩個二進制串同一列的數。求最少的操作次數,使得每一行含有的1的數量相等。
input:
第一行是測試案例的數目。
每個測試案例的第一行包含兩個字符n, m(2 ≤ n ≤ 10^5, 2 ≤ m ≤ 10^5)。
接下來n行每行包含m個僅為0或1的數字,是二進制串的具體內容。
output:
如果沒有辦法做到每行含有的1數目相等,輸出-1,否則在第一行輸出最少的操作次數k,
然后接下來k行,每行輸出三個字符,其中前兩個是選中的行,第三個是選中的列
Sample input:
3
3 4
1 1 1 0
0 0 1 0
1 0 0 1
4 3
1 0 0
0 1 1
0 0 1
0 0 0
2 2
0 0
0 1
Sample output:
1
2 1 1
1
4 2 2
-1
先統計每行1的個數, 并且計算出來每行應該有多少個。然后按列遍歷,對于第j列, 如果第i行1的個數多于平均值并且g[i][j]是1的話就記錄下來,如果第i行1的個數小于平均值并且g[i][j]是0的話也記錄下來。
Code:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
#define int LL
struct Node {
int x, y, z;
};
void solve(void) {
int n, m; cin >> n >> m;
int cnt = 0; int f[n + 1];
memset(f, 0, sizeof f);
vector<int> g[n + 1];
for(int i = 1; i <= n; i ++) {
g[i].resize(m + 1);
for(int j = 1; j <= m; j ++) {
cin >> g[i][j];
if(g[i][j]) {
cnt ++;
f[i] ++;
}
}
}
if(cnt % n) {
cout << "-1\n";
return;
}
cnt /= n;
vector<Node> ans;
for(int i = 1; i <= m; i ++) {
queue<int> que1, que2;
for(int j = 1; j <= n; j ++) {
if(f[j] > cnt && g[j][i]) que1.push(j);
if(f[j] < cnt && !g[j][i]) que2.push(j);
}
while(que1.size() && que2.size()) {
int x = que1.front();
int y = que2.front();
que1.pop();
que2.pop();
f[x] --; f[y] ++;
ans.push_back({x, y, i});
}
}
cout << ans.size() << '\n';
for(int i = 0; i < ans.size(); i ++) {
cout << ans[i].x << ' ' << ans[i].y << ' ' << ans[i].z << '\n';
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int t; cin >> t;
while(t --) solve();
}

浙公網安備 33010602011771號