/** * author: tsuyu93 * started: 2021-04-17 02:36:14 * 継続は力なり、雨だれ石を穿つ * make the impossible possible **/ #pragma GCC optimize("Ofast") #include #include using namespace atcoder; // #include // #include // namespace mpb = boost::multiprecision; // using bint = mpb::cpp_int; // // 仮数部が1024ビットの浮動小数点数型(TLEしたら小さくする) // using Real = mpb::number>; #ifdef __HOGE__ #pragma region macro #endif using namespace std; using ll = long long; using ld = long double; using ull = unsigned long long; using uint = unsigned; using pll = pair; using pli = pair; using pii = pair; using pld = pair; using ppiii = pair; using ppiill = pair; using ppllll = pair; using pplii = pair; using mii = map; using dll = deque; using qll = queue; using pqll = priority_queue; using pqrll = priority_queue, greater>; using pqrpll = priority_queue, greater>; using vint = vector; using vbool = vector; using vstr = vector; using vll = vector; using vld = vector; using vpll = vector; using vvll = vector>; using vvint = vector>; using vvld = vector>; using vvbool = vector; using vvstr = vector; using vvpll = vector>; #define REP(i,n) for(ll i=0;i=0;i--) #define FOR(i,a,b) for(ll i=a;i<=ll(b);i++) #define FORD(i,a,b) for(ll i=a;i>=ll(b);i--) #define overload4(_1,_2,_3,_4,name,...) name #define overload3(_1,_2,_3,name,...) name #define rep1(n) for(ll i=0;i(a);) #define rrep4(i,a,b,c) for(ll i=(a)+((b)-(a)-1)/(c)*(c);i>=(a);i-=c) #define rrep(...) overload4(__VA_ARGS__,rrep4,rrep3,rrep2,rrep1)(__VA_ARGS__) #define each1(i,a) for(auto&&i:a) #define each2(x,y,a) for(auto&&[x,y]:a) #define each3(x,y,z,a) for(auto&&[x,y,z]:a) #define each(...) overload4(__VA_ARGS__,each3,each2,each1)(__VA_ARGS__) #define all1(i) begin(i),end(i) #define all2(i,a) begin(i),begin(i)+a #define all3(i,a,b) begin(i)+a,begin(i)+b #define all(...) overload3(__VA_ARGS__,all3,all2,all1)(__VA_ARGS__) #define rall1(i) (i).rbegin(),(i).rend() #define rall2(i,k) (i).rbegin(),(i).rbegin()+k #define rall3(i,a,b) (i).rbegin()+a,(i).rbegin()+b #define rall(...) overload3(__VA_ARGS__,rall3,rall2,rall1)(__VA_ARGS__) #define SUM(...) accumulate(all(__VA_ARGS__),0LL) #define ALL(x) x.begin(),x.end() #define rALL(x) x.rbegin(),x.rend() #define SIZE(x) ll(x.size()) #define Sort(a) sort(all(a)) #define INT(...) int __VA_ARGS__;in(__VA_ARGS__) #define LL(...) ll __VA_ARGS__;in(__VA_ARGS__) #define ULL(...) ull __VA_ARGS__;in(__VA_ARGS__) #define STR(...) string __VA_ARGS__;in(__VA_ARGS__) #define CHR(...) char __VA_ARGS__;in(__VA_ARGS__) #define DBL(...) double __VA_ARGS__;in(__VA_ARGS__) #define LD(...) ld __VA_ARGS__;in(__VA_ARGS__)int scan(){ return getchar(); } #define fs first #define sc second #define endl '\n' #define elif else if void scan(int& a){ scanf("%d", &a); } void scan(unsigned& a){ scanf("%u", &a); } void scan(long& a){ scanf("%ld", &a); } void scan(long long& a){ scanf("%lld", &a); } void scan(unsigned long long& a){ scanf("%llu", &a); } void scan(char& a){ do{ a = getchar(); }while(a == ' ' || a == '\n'); } void scan(float& a){ scanf("%f", &a); } void scan(double& a){ scanf("%lf", &a); } void scan(long double& a){ scanf("%Lf", &a); } void scan(vector& a){ for(unsigned i = 0; i < a.size(); i++){ int b; scan(b); a[i] = b; } } void scan(char a[]){ scanf("%s", a); } void scan(string& a){ cin >> a; } template void scan(vector&); template void scan(array&); template void scan(pair&); template void scan(T(&)[size]); template void scan(vector& a){ for(auto&& i : a) scan(i); } template void scan(deque& a){ for(auto&& i : a) scan(i); } template void scan(array& a){ for(auto&& i : a) scan(i); } template void scan(pair& p){ scan(p.first); scan(p.second); } template void scan(T (&a)[size]){ for(auto&& i : a) scan(i); } template void scan(T& a){ cin >> a; } void in(){} template void in(Head& head, Tail&... tail){ scan(head); in(tail...); } void print(){ putchar(' '); } void print(bool a){ printf("%d", a); } void print(int a){ printf("%d", a); } void print(unsigned a){ printf("%u", a); } void print(long a){ printf("%ld", a); } void print(long long a){ printf("%lld", a); } void print(unsigned long long a){ printf("%llu", a); } void print(char a){ printf("%c", a); } void print(char a[]){ printf("%s", a); } void print(const char a[]){ printf("%s", a); } void print(float a){ printf("%.15f", a); } void print(double a){ printf("%.15f", a); } void print(long double a){ printf("%.15Lf", a); } void print(const string& a){ for(auto&& i : a) print(i); } template void print(const complex& a){ if(a.real() >= 0) print('+'); print(a.real()); if(a.imag() >= 0) print('+'); print(a.imag()); print('i'); } template void print(const vector&); template void print(const array&); template void print(const pair& p); template void print(const T (&)[size]); template void print(const vector& a){ if(a.empty()) return; print(a[0]); for(auto i = a.begin(); ++i != a.end(); ){ putchar(' '); print(*i); } } template void print(const deque& a){ if(a.empty()) return; print(a[0]); for(auto i = a.begin(); ++i != a.end(); ){ putchar(' '); print(*i); } } template void print(const array& a){ print(a[0]); for(auto i = a.begin(); ++i != a.end(); ){ putchar(' '); print(*i); } } template void print(const pair& p){ print(p.first); putchar(' '); print(p.second); } template void print(const T (&a)[size]){ print(a[0]); for(auto i = a; ++i != end(a); ){ putchar(' '); print(*i); } } template void print(const T& a){ cout << a; } int out(){ putchar('\n'); return 0; } template int out(const T& t){ print(t); putchar('\n'); return 0; } template int out(const Head& head, const Tail&... tail){ print(head); putchar(' '); out(tail...); return 0; } #ifdef DEBUG inline ll __lg(ull x){ return 63 - __builtin_clzll(x); } #define debug(...) { print(#__VA_ARGS__); print(":"); out(__VA_ARGS__); } #else #define debug(...) void(0) #endif #define INF32 2147483647 //2.147483647x10^{9}:32bit整数のinf #define INF64 9223372036854775807 //9.223372036854775807x10^{18}:64bit整数のinf const ll MOD = 1000000007; const int inf = 1e9; const ll INF = 0x7f7f7f7f7f7f7f7f; const ll MAXR = 100000; //10^5:配列の最大のrange const ld PI = acos(-1); inline void Yes(bool b = true) { cout << (b ? "Yes" : "No") << '\n'; } inline void YES(bool b = true) { cout << (b ? "YES" : "NO") << '\n'; } inline void OKNG(bool b = true) { cout << (b ? "OK" : "NG") << '\n'; } inline void possible(bool i = true){ cout << (i?"possible":"impossible") << '\n'; } inline void Possible(bool i = true){ cout << (i?"Possible":"Impossible") << '\n'; } inline void POSSIBLE(bool i = true){ cout << (i?"POSSIBLE":"IMPOSSIBLE") << '\n'; } template inline bool chmin(A& a, B b) {if (a > b) {a = b;return true;}return false;} template inline bool chmax(A& a, B b) {if (a < b) {a = b;return true;}return false;} template auto min(const T& a){ return *min_element(a.begin(),a.end()); } template auto max(const T& a){ return *max_element(a.begin(),a.end()); } template A power(A a, A b) {A res=1;while (b>0) {if (b&1){res*=a;}b/=2;a*=a;}return res;} long long powmod(long long a, long long b) {long long res=1;while (b>0) {if (b&1){res*=a;res%=MOD;}b/=2;a*=a;a%=MOD;}return res;} template A powmod(A a, A b,A m) {A res=1;while (b>0) {if (b&1){res*=a;res%=m;}b/=2;a*=a;a%=m;}return res%m;} template A nlcm(vector a) {A res;res = a[0];for (ll i = 1; i < (ll)a.size(); i++) {res = lcm(res, a[i]);}return res;} template A ngcd(vector a){A res;res = a[0];for(ll i = 1; i < (ll)a.size() && res != 1; i++) {res = gcd(a[i], res);}return res;} template A sqr(A x){A r=sqrt(x)-1;while((r+1)*(r+1)<=x)r++;return r;} template A bit_length(A a){A k = 0;while(a){k++;a/=2;}return k;} template A isqrt(A n){A a = 0, r = 0;for(A s = bit_length(n)-(bit_length(n)%2?1:2); s >= 0;s-=2){A t = ((n >> s) & 3);r = ((r << 2) | t);A c = ((a << 2) | 1);int b = (r >= c);if(b){r -= c;}a = ((a << 1) | b);}return a;} #ifdef __HOGE__ #pragma endregion #endif template vector compress(vector &A){ sort(A.begin(), A.end()); A.erase(unique(A.begin(), A.end()), A.end()); return A; } template vector press(vector &x){ auto res=x; sort(res.begin(),res.end()); res.erase(unique(res.begin(),res.end()),res.end()); for(auto &xx:x){ xx=lower_bound(res.begin(),res.end(),xx)-res.begin(); } return res; } signed main(){ ios::sync_with_stdio(false); cin.tie(nullptr); //cout << fixed << setprecision(15); ll H,W; cin >> H >> W; vvll A(H,vll(W)); rep(i,H)rep(j,W){ cin >> A[i][j]; } map> mp; rep(i,H)rep(j,W){ if(A[i][j]==0)continue; mp[A[i][j]].insert({i,j}); } ll ans = 0; for(auto[i,ste]:mp){ if(ste.empty())continue; if(ste.size()==1){ans++;continue;} mf_graph graph(H+W+2); ll st = H+W, ed = H+W+1; vll he,we; for(auto[h,w] : ste){ he.push_back(h); we.push_back(w); graph.add_edge(h,w+H,1); } sort(he.begin(), he.end()); he.erase(unique(he.begin(), he.end()), he.end()); sort(we.begin(), we.end()); we.erase(unique(we.begin(), we.end()), we.end()); for(auto h:he){ graph.add_edge(st,h,1); } for(auto w:we){ graph.add_edge(w+H,ed,1); } ans+= graph.flow(st,ed); } cout << ans << endl; return 0; }