#include <bits/stdc++.h>
using namespace std;
class Graph {
 public:
  vector<vector<int>> a;
  vector<int> vis;
  int N, M;
  int n;
  int R(int i) { return i; }
  int C(int i) { return i + N; }
  void addEdge(int l, int r) {
    a[R(l)].push_back(C(r));
    a[C(r)].push_back(R(l));
  }
  Graph() {
    cin >> N >> M;
    n = N + M;
    a.assign(n, vector<int>());
    vis.assign(n, 0);
    for (int i = 0; i < int(N); i++) {
      cin.get();
      for (int j = 0; j < int(M); j++) {
        char c = cin.get();
        if (c == '.') continue;
        addEdge(i, j);
      }
    }
  }
  bool dfs(int v, set<int> &r, set<int> &c) {
    vis[v] = 1;
    if (v < N && a[v].size() != c.size()) return 0;
    if (v >= N && a[v].size() != r.size()) return 0;
    for (int to : a[v]) {
      if (!vis[to] && !dfs(to, r, c)) return 0;
      if (v < N && !c.count(to)) return 0;
      if (v >= N && !r.count(to)) return 0;
    }
    return 1;
  }
  bool isCompleteBipariate(int v) {
    if (a[v].empty()) return 1;
    set<int> c((a[v]).begin(), (a[v]).end());
    set<int> r((a[a[v][0]]).begin(), (a[a[v][0]]).end());
    return dfs(v, r, c);
  }
  void solve() {
    for (int i = 0; i < int(N); i++)
      if (!vis[i] && !isCompleteBipariate(i)) {
        cout << "No" << endl;
        return;
      }
    cout << "Yes" << endl;
  }
};
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(nullptr);
  cout.tie(nullptr);
  Graph g;
  g.solve();
}
