#include <bits/stdc++.h>

#define rep(i,n) for(int i=0;i<(int)(n);i++)
#define FOR(i,n,m) for(int i=(int)(n); i<=(int)(m); i++)
#define RFOR(i,n,m) for(int i=(int)(n); i>=(int)(m); i--)
#define ITR(x,c) for(__typeof(c.begin()) x=c.begin();x!=c.end();x++)
#define RITR(x,c) for(__typeof(c.rbegin()) x=c.rbegin();x!=c.rend();x++)
#define setp(n) fixed << setprecision(n)

template<class T> bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T> bool chmin(T &a, const T &b) { if (a>b) { a=b; return 1; } return 0; }

#define ll long long
#define vll vector<ll>
#define vi vector<int>
#define pll pair<ll,ll>
#define pi pair<int,int>

#define all(a) (a.begin()),(a.end())
#define rall(a) (a.rbegin()),(a.rend())
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define ins insert

using namespace std;

#define INF 1e9

//-------------------------------------------------
//--Rich Set (Treap)
//-------------------------------------------------
template <class T>
class RichMultiSet
{
protected:
    struct Node {
        Node *child[2];
        T key,sum;
        uint32_t pri;
        int weight;
        Node(){}
        Node(T key, uint32_t pri):key(key),sum(key),pri(pri),weight(1){
            child[0]=child[1]=nullptr;
        }
    };
    using np = Node*;
    using F = function<T(T,T)>;

    np root;
    int n,ptr;
    vector<Node> buf;
    const T e; const F f;

    uint32_t xorshift(){
        static uint32_t x = 123456789;
        static uint32_t y = 362436069;
        static uint32_t z = 521288629;
        static uint32_t w = 88675123;
        uint32_t t;
        t = x ^ (x<<11);
        x = y; y = z; z = w;
        w ^= t ^ (t>>8) ^ (w>>19);
        return w;
    }

    inline np make_node(const T &key, uint32_t pri, bool dummy){
        assert(ptr<n);
        np ret = &(buf[ptr]=Node(key,pri));
        if (!dummy) ptr++;
        return ret;
    }

    inline int weight(np t){return t ? t->weight : 0;}
    inline T sum(np t){return t ? t->sum : e;}
    inline np update(np t){
        t->weight = weight(t->child[0])+weight(t->child[1])+1;
        t->sum = f(f(sum(t->child[0]),t->key),sum(t->child[1]));
        return t;
    }
    np rotate(np t, int dir){
        np s = t->child[dir];
        t->child[dir] = s->child[1-dir];
        s->child[1-dir] = t;
        update(t); update(s);
        return s;
    }
    np insert(np t, int k, const T &key, uint32_t pri, bool dummy=false){
        if (empty()) return root = make_node(key,pri,dummy);
        if (!t) return make_node(key,pri,dummy);
        int c=weight(t->child[0]), dir=k>c;
        t->child[dir] = insert(t->child[dir], k-dir*(c+1), key, pri, dummy);
        update(t);
        if (t->pri >= t->child[dir]->pri) t = rotate(t,dir);
        return t;
    }
    np erase(np t, const T &key){
        if (!t) return nullptr;
        bool rot = (key==t->key);
        int dir = (rot)?(weight(t->child[0]) > weight(t->child[1])):(key > t->key);
        if (!t->child[dir] && rot) return t->child[1-dir];
        if (rot) t = rotate(t,1-dir);
        t->child[dir] = erase(t->child[dir],key);
        update(t);
        return t;
    }
    pair<np,np> split(np t, int k){
        t = insert(t,k,e,0,true);
        return make_pair(t->child[0], t->child[1]);
    }
    np merge(np left, np right){
        np t = make_node(e,0,true);
        t->child[0] = left; t->child[1] = right;
        update(t);
        return erase(t,e);
    }
    int lower_bound(np t, const T &key){
        if (!t) return 0;
        if (key <= t->key) return lower_bound(t->child[0],key);
        return lower_bound(t->child[1],key)+weight(t->child[0])+1;
    }
    int upper_bound(np t, const T &key){
        if (!t) return 0;
        if (key < t->key) return upper_bound(t->child[0],key);
        return upper_bound(t->child[1],key)+weight(t->child[0])+1;
    }
    T get(np t, int k){
        assert(t);
        int c=weight(t->child[0]), dir=k>c;
        if (c==k) return t->key;
        return get(t->child[dir], k-dir*(c+1));
    }
public:
    RichMultiSet(int n,F f=[](T a,T b){return a+b;},T e=0):n(n),buf(n),ptr(0),root(nullptr),f(f),e(e){}
    inline bool empty(){return !root;}
    inline int size(){return weight(root);}
    inline int lower_bound(const T &key){return lower_bound(root,key);}
    inline int upper_bound(const T &key){return upper_bound(root,key);}

    int count(const T &key){return upper_bound(root,key)-lower_bound(root,key);}
    void insert(const T &key){root = insert(root,lower_bound(root,key),key,xorshift());}
    void erase(const T &key){root = erase(root,key);}
    T query(int a, int b){
        auto p = split(root,a);
        auto q = split(p.second,b-a);
        T ret = sum(q.first);
        root = merge(p.first, merge(q.first, q.second));
        return ret;
    }
    inline T operator[](int k){return get(root,k);}
};

template <class T>
class RichSet : public RichMultiSet<T>
{
private:
    using RichMultiSet<T>::count;
    using RichMultiSet<T>::root;
    using RichMultiSet<T>::insert;
    using RichMultiSet<T>::xorshift;
    using RichMultiSet<T>::lower_bound;
public:
    using RichMultiSet<T>::RichMultiSet;
    void insert(const T &key){
        if (count(key)) return;
        root = insert(root,lower_bound(root,key),key,xorshift());
    }
};

// RichMultiSetは
// lower_bound, upper_boundでindexを得られ
// セグ木と同様にモノイドをのせて範囲queryをO(logN)でできます

// 最初にS_iを見ていき，内部で対応してしまう文字は無視すると
// ")))....)(((...("と同義だと扱える
// 片方の向きの括弧しか存在しないものは端に追いやるのがどう考えても最適なのでそうする

// 両方の向きの括弧があるS_iを中央部を左から埋めていくことを考えて，S_iで埋める操作を
//      左側にある'('のストックを，S_i中の')'の個数だけ消費して'('の数だけ生産する操作
// と考えられる．よって，
// 現在の'('のストックを超えない消費のS_iの中から(生産-消費)が最も大きいものから埋めていった

// 具体的には，まずcntを用いて全体の生産-消費は0になることを確認
// 生産のみ/消費のみのS_iに関してはその生産数をright, 消費数をleftに足していく(leftは使っていない)
// 両方の括弧からなるS_iに関しては，{消費個数, 生産-消費}のペアを消費個数ソートでRichMultiSetに挿入

// 要素数をKとしてKループ
// RichMultiSetには(生産-消費)のmaxのペアを返すクエリを処理してもらう
// あとは逐一消費がsave(ストック)以下の消費のペアの右端+1をupper_boundで求める
// そのようなペアがなければ埋められないのでNo
// これを繰り返し全部埋められたらYes

// ※嘘っぽい

//-------------------------------------------------

int main(void)
{
    cin.tie(0);
    ios::sync_with_stdio(false);
    int N; cin>>N;
    auto f = [](pi a, pi b){
        return (a.se>b.se)?a:b;
    };
    RichMultiSet<pi> rs(N+1, f, {0,-INF});
    int cnt=0;
    int left=0,right=0;
    rep(i,N){
        string s; cin>>s;
        int L=0, R=0;
        int M = s.size();
        int nest=0;
        rep(j,M){
            if (s[j]=='(') nest++;
            if (s[j]==')'){
                if (nest>0) nest--;
                else L++;
            }
        }
        R = nest;
        cnt+=L; cnt-=R;
        if (L==0){
            right+=R;
        }else if(R==0){
            left+=L;
        }else{
            rs.ins({L,R-L});
        }
    }
    if (cnt!=0){
        cout<<"No\n";
        return 0;
    }
    int K=rs.size();
    int save=right;
    rep(i,K){
        int j = rs.upper_bound({save,INF});
        if (j==0){
            cout<<"No\n";
            return 0;
        }
        auto t = rs.query(0,j);
        save+=t.se;
        rs.erase(t);
    }
    cout<<"Yes\n";
    return 0;
}


Measured memory_bytes: 42248