- //by emanlaicepsa
- #include<bits/stdc++.h>
- #define ll long long
- #define int ll
- #define IOS ios::sync_with_stdio(0),cin.tie(0);
- #define pb push_back
- #define pii pair<int,int>
- #define fi first
- #define se second
- #define all(n) (n).begin(),(n).end()
- #define mem(n,k) memset(n,k,sizeof(n))
- using namespace std;
- template <typename T>
- struct hungarian { // km
- int n;
- vector<int> matchx;
- vector<int> matchy;
- vector<int> pre;
- vector<bool> visx;
- vector<bool> visy;
- vector<T> lx;
- vector<T> ly;
- vector<vector<T> > g;
- vector<T> slack;
- T inf;
- T res;
- queue<int> q;
- int org_n;
- int org_m;
- hungarian(int _n, int _m) {
- org_n = _n;
- org_m = _m;
- n = max(_n, _m);
- inf = numeric_limits<T>::max();
- res = 0;
- g = vector<vector<T> >(n, vector<T>(n));
- matchx = vector<int>(n, -1);
- matchy = vector<int>(n, -1);
- pre = vector<int>(n);
- visx = vector<bool>(n);
- visy = vector<bool>(n);
- lx = vector<T>(n, -inf);
- ly = vector<T>(n);
- slack = vector<T>(n);
- }
- void addEdge(int u, int v, int w) {
- g[u][v] = max(w, 0LL);
- }
- bool check(int v) {
- visy[v] = true;
- if (matchy[v] != -1) {
- q.push(matchy[v]);
- visx[matchy[v]] = true;
- return false;
- }
- while (v != -1) {
- matchy[v] = pre[v];
- swap(v, matchx[pre[v]]);
- }
- return true;
- }
- void bfs(int i) {
- while (!q.empty()) {
- q.pop();
- }
- q.push(i);
- visx[i] = true;
- while (true) {
- while (!q.empty()) {
- int u = q.front();
- q.pop();
- for (int v = 0; v < n; v++) {
- if (!visy[v]) {
- T delta = lx[u] + ly[v] - g[u][v];
- if (slack[v] >= delta) {
- pre[v] = u;
- if (delta) {
- slack[v] = delta;
- } else if (check(v)) {
- return;
- }
- }
- }
- }
- }
- // ?有增?路 修改??
- T a = inf;
- for (int j = 0; j < n; j++) {
- if (!visy[j]) {
- a = min(a, slack[j]);
- }
- }
- for (int j = 0; j < n; j++) {
- if (visx[j]) { // S
- lx[j] -= a;
- }
- if (visy[j]) { // T
- ly[j] += a;
- } else { // T'
- slack[j] -= a;
- }
- }
- for (int j = 0; j < n; j++) {
- if (!visy[j] && slack[j] == 0 && check(j)) {
- return;
- }
- }
- }
- }
- int solve() {
- // 初始??
- for (int i = 0; i < n; i++) {
- for (int j = 0; j < n; j++) {
- lx[i] = max(lx[i], g[i][j]);
- }
- }
- for (int i = 0; i < n; i++) {
- fill(slack.begin(), slack.end(), inf);
- fill(visx.begin(), visx.end(), false);
- fill(visy.begin(), visy.end(), false);
- bfs(i);
- }
- // custom
- for (int i = 0; i < n; i++) {
- if (g[i][matchx[i]] > 0) {
- res += g[i][matchx[i]];
- } else {
- matchx[i] = -1;
- }
- }
- return res;
- cout << res << "\n";
- for (int i = 0; i < org_n; i++) {
- cout << matchx[i] + 1 << " ";
- }
- cout << "\n";
- }
- };
- int arr[105][105],nx,ny;
- int mr[105] , mc[105];
- signed main(){
- //IOS;
- //mem(w,-1);
- cin>>nx>>ny;
- hungarian<long long> solver(nx, ny);
- int tot = 0, cnt = 0;
- for(int i=0;i<nx;i++){
- for(int j=0;j<ny;j++){
- cin>>arr[i][j];
- cnt += (arr[i][j] > 0);
- tot += (arr[i][j]);
- }
- }
- for(int i=0;i<nx;i++){
- mr[i] = 0;
- for(int j=0;j<ny;j++){
- mr[i] = max(mr[i],arr[i][j]);
- }
- }
- for(int j=0;j<ny;j++){
- mc[j] = 0;
- for(int i=0;i<nx;i++){
- mc[j] = max(mc[j],arr[i][j]);
- }
- }
- int ans = cnt;
- for(int i=0;i<nx;i++) ans += mr[i] , ans -= (mr[i] != 0);
- for(int i=0;i<ny;i++) ans += mc[i] , ans -= (mc[i] != 0);
- for(int i=0;i<nx;i++){
- if(mr[i] == 0) continue;
- for(int j=0;j<ny;j++){
- if(mr[i] == mc[j] && arr[i][j] != 0){
- solver.addEdge(i,j,mr[i]-1);
- }
- }
- }
- //cout<<solver.solve()<<'\n';
- ans -= solver.solve();
- cout<<tot-ans<<'\n';
- //cout<<"HI\n";
- //ans -= KM();
- //cout<<tot-ans<<'\n';
- }