#include <vector>
#include <array>
#include <stack>
#include <queue>
#include <list>
#include <bitset>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <algorithm>
#include <numeric>
#include <iostream>
#include <iomanip>
#include <string>
#include <chrono>
#include <random>
#include <cmath>
#include <cassert>
#include <climits>
#include <cstring>
#include <cstdlib>
#include <functional>
#include <sstream>

using namespace std;


class DisjointSet {
    public:
        DisjointSet(int n) : N(n), sz(n), pars(n, -1) {
        }
        void reset() { sz = N, fill(pars.begin(), pars.end(), -1); }
        int find(int x) { return pars[x] < 0 ? x : pars[x] = find(pars[x]); }
        int size() { return sz; }
        int count(int x) { return -pars[find(x)]; }
        bool unite(int x, int y) {
            x = find(x), y = find(y);
            if (x == y) { return false; }
            --sz;
            if (pars[x] < pars[y]) { swap(x, y); }
            pars[y] += pars[x];
            pars[x] = y;
            return true;
        }
        bool isSame(int x, int y) { return find(x) == find(y); }
    private:
        int N, sz;
        vector<int> pars;
};

int main(int argc, char** argv) {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout << fixed << setprecision(12);

    int n, m;
    cin >> n >> m;
    vector<string> S(n);
    for (int i = 0; i < n; ++i) {
        cin >> S[i];
    }

    DisjointSet ds(n + m);
    ds.unite(0, n - 1);
    ds.unite(0, n);
    ds.unite(0, n + m - 1);

    vector<int> X{-1, 1, 0, 0};
    vector<int> Y{0, 0, -1, 1};
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < m; ++j) {
            if (S[i][j] == '#') {
                ds.unite(i, n + j);
            }
        }
    }

    set<int> R;
    set<int> C;
    int res = 0;
    for (int i = 0; i < n; ++i) {
        R.insert(ds.find(i));
    }
    for (int i = 0; i < m; ++i) {
        C.insert(ds.find(n + i));
    }

    res = min(R.size() - 1, C.size() - 1);
    cout << res << '\n';
    
    return 0;
}
#include<bits/stdc++.h>

using namespace std;

#define rep(x, L, R) for(int x = (L), _x = (R); x <= _x; x++)
#define per(x, R, L) for(int x = (R), _x = (L); x >= _x; x--)
#define broken fprintf(stderr, "running on %s %d\n", __FUNCTION__, __LINE__)
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define SZ(v) (int)(v).size()
#define ALL(x) (x).begin(), (x).end()
#define x first
#define y second
#define mp make_pair
#define pb push_back

template<typename T> inline bool ckmin(T &a, const T &b) { return b < a ? a = b, 1 : 0; }
template<typename T> inline bool ckmax(T &a, const T &b) { return a < b ? a = b, 1 : 0; }

typedef pair<int, int> par;
typedef long long LL;
typedef unsigned long long uLL;
typedef double db;
const int N = 2e5 + 10, inf = 0x3f3f3f3f;
int n, k;
int a[N], b[N];
vector<int> g[N];

void adde(int u, int v) { g[u].push_back(v); }

void dfs(int u, int fa, int k, int &cnt) {
	int mn = n * 2, smn = n * 2;
	a[u] = b[u] = 0;
	for(auto v : g[u]) {
		if(v == fa) continue;
		dfs(v, u, k, cnt);
		if(mn > b[v]) smn = mn, mn = b[v];
		else smn = min(smn, b[v]);
	}
	for(auto v : g[u]) {
		if(v == fa) continue;
		int now = mn;
		if(b[v] == now) now = smn;
		if(now + 2 + a[v] <= k) a[v] = - n * 2;
		else a[u] = max(a[u], a[v] + 1);
	}
	if(mn + 1 <= k && a[u] <= 0) a[u] = - n * 2;
	if(a[u] >= k) cnt++, a[u] = - n * 2, b[u] = 0;
	else b[u] = mn + 1;
	return;
}

int check(int k) {
	int cnt = 0;
	dfs(1, 0, k, cnt);
	if(a[1] >= 0) cnt++;
	return cnt;
}

int main() {
	scanf("%d%d", &n, &k);
	rep(i, 1, n - 1) {
		int u, v;
		scanf("%d%d", &u, &v);
		adde(u, v), adde(v, u);
	}
	int l = 0, r = n, best = -1;
	while(l <= r) {
		int mid = (l + r) / 2;
		if(check(mid) <= k) best = mid, r = mid - 1;
		else l = mid + 1;
	}
	printf("%d\n", best);
	return 0;
}

