    #include <bits/stdc++.h>

                                            //    #include <boost/multiprecision/cpp_int.hpp>

                               	       #define int long long
                                                #define inf  1000000007
                                              #define pa pair<int,int>
                                               #define pad pair<double,double>
                                                #define ll long long
                                                #define pal pair<double,double>
                                                #define ppap pair<pa,int>
                                          #define PI 3.14159265358979323846
                                                #define paa pair<pa,pa>
                                                #define  mp make_pair
                                                #define  pb push_back
                                                #define EPS (1e-10)
                                                #define equals(a,b) (fabs((a)-(b))<EPS)
                                            //    #define double long double
        int dx[4]={0,-1,0,1};
        int dy[4]={1,0,-1,0};
                                                using namespace std;
                                       			class pa3{
                                                	public:
                                                	int x,y,z;
                                                	pa3(int x=0,int y=0,int z=0):x(x),y(y),z(z) {}
                                                	bool operator < (const pa3 &p) const{
                                                		if(x!=p.x) return x<p.x;
                                                		if(y!=p.y) return y<p.y;
                                                		 return z<p.z;
                                                		//return x != p.x ? x<p.x: y<p.y;
                                                	}
                                       				bool operator > (const pa3 &p) const{
                                                		if(x!=p.x) return x>p.x;
                                                		if(y!=p.y) return y>p.y;
                                                		 return z>p.z;
                                                		//return x != p.x ? x<p.x: y<p.y;
                                                	}
                                                	bool operator == (const pa3 &p) const{
                                                		return x==p.x && y==p.y && z==p.z;
                                                	}
                                                		bool operator != (const pa3 &p) const{
                                                			return !( x==p.x && y==p.y && z==p.z);
                                                	}

                                                };

                                                class pa4{
                                                	public:
                                                	int x;
                                                	int y,z,w;
                                                	pa4(int x=0,int y=0,int z=0,int w=0):x(x),y(y),z(z),w(w) {}
                                                	bool operator < (const pa4 &p) const{
                                                		if(x!=p.x) return x<p.x;
                                                		if(y!=p.y) return y<p.y;
                                                		if(z!=p.z)return z<p.z;
                                                		return w<p.w;
                                                		//return x != p.x ? x<p.x: y<p.y;
                                                	}
                                                	bool operator > (const pa4 &p) const{
                                                		if(x!=p.x) return x>p.x;
                                                		if(y!=p.y) return y>p.y;
                                                		if(z!=p.z)return z>p.z;
                                                		return w>p.w;
                                                		//return x != p.x ? x<p.x: y<p.y;
                                                	}
                                                	bool operator == (const pa4 &p) const{
                                                		return x==p.x && y==p.y && z==p.z &&w==p.w;
                                                	}

                                                	bool operator != (const pa4 &p) const{
                                                		return !(x==p.x && y==p.y && z==p.z &&w==p.w);
                                                	}

                                                };
                                                class pa2{
                                                	public:
                                                	int x,y;
                                                	pa2(int x=0,int y=0):x(x),y(y) {}
                                                	pa2 operator + (pa2 p) {return pa2(x+p.x,y+p.y);}
                                                	pa2 operator - (pa2 p) {return pa2(x-p.x,y-p.y);}
                                                	bool operator < (const pa2 &p) const{
                                                		return x!= p.x ? x<p.x: y<p.y;
                                                	}
                                                	bool operator > (const pa2 &p) const{
                                                		return x != p.x ? x>p.x: y>p.y;
                                                	}
                                                	bool operator == (const pa2 &p) const{
                                                		return abs(x-p.x)==0 && abs(y-p.y)==0;
                                                	}
                                                	bool operator != (const pa2 &p) const{
                                                		return !(abs(x-p.x)==0 && abs(y-p.y)==0);
                                                	}

                                                };

                                                       #define ppa pair<int,pas>
                                                class Point{
                                                	public:
                                                	double x,y;
                                                	Point(double x=0,double y=0):x(x),y(y) {}
                                                	Point operator + (Point p) {return Point(x+p.x,y+p.y);}
                                                	Point operator - (Point p) {return Point(x-p.x,y-p.y);}
                                                	Point operator * (double a) {return Point(x*a,y*a);}
                                                	Point operator / (double a) {return Point(x/a,y/a);}
                                                	double absv() {return sqrt(norm());}
                                                	double norm() {return x*x+y*y;}
                                                	bool operator < (const Point &p) const{
                                                		return x != p.x ? x<p.x: y<p.y;
                                                	}
                                                	bool operator == (const Point &p) const{
                                                		return fabs(x-p.x)<EPS && fabs(y-p.y)<EPS;
                                                	}
                                                };
                                                typedef Point Vector;
                                         #define pl pair<int,pas>
                                                struct Segment{
                                                Point p1,p2;
                                                };
                                                 double dot(Vector a,Vector b){
                                                	return a.x*b.x+a.y*b.y;
                                                }
                                                double cross(Vector a,Vector b){
                                                	return a.x*b.y-a.y*b.x;
                                                }

                    bool parareru(Point a,Point b,Point c,Point d){
                    //	if(abs(cross(a-b,d-c))<EPS)cout<<"dd "<<cross(a-b,d-c)<<endl;
                    	return abs(cross(a-b,d-c))<EPS;
                    }
                    double distance_ls_p(Point a, Point b, Point c) {
                      if ( dot(b-a, c-a) < EPS ) return (c-a).absv();
                      if ( dot(a-b, c-b) < EPS ) return (c-b).absv();
                      return abs(cross(b-a, c-a)) / (b-a).absv();
                    }
                    bool is_intersected_ls(Segment a,Segment b) {
                    	if(a.p1==b.p1||a.p2==b.p1||a.p1==b.p2||a.p2==b.p2) return false;
                    	if(parareru((a.p2),(a.p1),(a.p1),(b.p2))&&parareru((a.p2),(a.p1),(a.p1),(b.p1))){
                    //		cout<<"sss"<<endl;
                    		if(dot(a.p1-b.p1,a.p1-b.p2)<EPS) return true;
                    		if(dot(a.p2-b.p1,a.p2-b.p2)<EPS) return true;
                    		if(dot(a.p1-b.p1,a.p2-b.p1)<EPS) return true;
                    		if(dot(a.p1-b.p2,a.p2-b.p2)<EPS) return true;
                    		return false;
                    	}
                      else return ( cross(a.p2-a.p1, b.p1-a.p1) * cross(a.p2-a.p1, b.p2-a.p1) < EPS ) && ( cross(b.p2-b.p1, a.p1-b.p1) * cross(b.p2-b.p1, a.p2-b.p1) < EPS );
                    }

                    double segment_dis(Segment a,Segment b){
                    	if(is_intersected_ls(a,b))return 0;
                    	double r=distance_ls_p(a.p1, a.p2, b.p1);
                    	r=min(r,distance_ls_p(a.p1, a.p2, b.p2));
                    	r=min(r,distance_ls_p(b.p1, b.p2, a.p2));
                    	r=min(r,distance_ls_p(b.p1, b.p2, a.p1));
                    	return r;
                    }
                    Point intersection_ls(Segment a, Segment b) {
                      Point ba = b.p2-b.p1;
                      double d1 = abs(cross(ba, a.p1-b.p1));
                      double d2 = abs(cross(ba, a.p2-b.p1));
                      double t = d1 / (d1 + d2);

                      return a.p1 + (a.p2-a.p1) * t;
                    }

                                    string itos( int i ) {
                                    ostringstream s ;
                                    s << i ;
                                    return s.str() ;
                                    }

                                    int gcd(int v,int b){
                                    	if(v>b) return gcd(b,v);
                                    	if(v==b) return b;
                                    	if(b%v==0) return v;
                                    	return gcd(v,b%v);
                                    }

                                    double distans(double x1,double y1,double x2,double y2){
                                    	double rr=(x1-x2)*(x1-x2)+(y1-y2)*(y1-y2);
                                    	return sqrt(rr);

                                    }
                                                        /*
        double bekid(double w,int r){
        	if(r==0) return 1.0;
        	if(r==1) return w;
        	if(r%2) return bekid(w,r-1)*w;
        	double f=bekid(w,r/2);
        	return f*f;
        }*/
                                    int mod;
                          /*
                    int pr[401000];
                    int inv[401000];

                    int beki(int wa,int rr,int warukazu){
                    	if(rr==0) return 1%warukazu;
                    	if(rr==1) return wa%warukazu;
                    	if(rr%2==1) return (beki(wa,rr-1,warukazu)*wa)%warukazu;
                    	int zx=beki(wa,rr/2,warukazu);
                    	return (zx*zx)%warukazu;
                    }

        			int comb(int nn,int rr){
        				int r=pr[nn]*inv[rr];
        				r%=mod;
        				r*=inv[nn-rr];
        				r%=mod;

        				return r;
        			}

                    void gya(int ert){
                    	pr[0]=1;
                    	for(int i=1;i<ert;i++){
                    		pr[i]=(pr[i-1]*i)%mod;
                    	}
                    	for(int i=0;i<ert;i++) inv[i]=beki(pr[i],mod-2,mod);

                    }
                    */

                  //   cin.tie(0);
        		//	ios::sync_with_stdio(false);
        			//priority_queue<pa3,vector<pa3>,greater<pa3>> pq;
                     //sort(ve.begin(),ve.end(),greater<int>());

                                          //----------------kokomade tenpure------------
bool a[1<<22]={0};
vector<int> ve;
bool sumi[1<<22]={0};
void dfs(int r){
	if(sumi[r]) return;
	sumi[r]=1;
	if(a[r]){
		ve.pb(r);
		a[r]=0;
	}
	for(int i=0;i<22;i++)if(r&(1<<i)){
		if(sumi[r^(1<<i)])continue;
		dfs(r^(1<<i));
	}
}
  signed main(){
 // 	              cin.tie(0);
   // 		ios::sync_with_stdio(false);
  	int f=(1<<22)-1;
  	int n,m;
  	cin>>n>>m;
  	for(int i=0;i<m;i++){
  		int y;
  		cin>>y;
  		a[y]=1;
  	}
  	int ans=0;
  	for(int i=0;i<(1<<22);i++)if(a[i]){
  		ans++;
  		a[i]=0;
  		ve.pb(i);
  	//	cout<<i<<endl;
  		while(ve.size()){
  			int g=ve.back();
  //			cout<<" "<<g<<endl;
  			ve.pop_back();
  			dfs(g^f);
  		}
  	}
  	cout<<ans<<endl;
  	return 0;
                }


#include<bits/stdc++.h>
#define pb push_back
#define mp make_pair
#define SZ(x) ((int)(x).size())
#define ALL(x) x.begin(),x.end()
#define fi first
#define se second
#define _upgrade ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);

using namespace std;

typedef long long LL;
typedef pair<int,int> PII;
typedef pair<LL,LL> PLL;
typedef vector<PII> VPII;
typedef vector<PLL> VPLL;
typedef vector<LL> VLL;
typedef vector<int> VI;
typedef vector<string> VS;
typedef vector<char> VC;
typedef long double LD;
typedef pair<LD,LD> PLD;
typedef vector<LD> VLD;
typedef vector<PLD> VPLD;
typedef map<int, int> MII;
typedef map<int, VI> MIVI;
typedef map<LL, LL> MLLLL;
typedef map<LL, VLL> MLLVLL;

template<typename T>
void dbg(T a)
{
      #ifdef LOCAL
            cerr<<a<<"\n";
      #endif
}

template<typename T, typename ...Arg>
void dbg(T a,Arg ...arg)
{
      #ifdef LOCAL
            cerr<<a<<" ";
            dbg(arg...);
      #endif
}

const int maxn = (1e6)+7;
const int inf = (1e9)+7;
const LL LLinf = (1e18)+7;
const LD eps = 1e-9;
const LL mod = 1e9+7;

// ***************************** CODE ***************************** //

int odp = 1;
VI wek[maxn], odw[maxn];
bool vis[maxn];
int skl[maxn];
stack<int> stos;

void dfs(int x)
{
      vis[x] = 1;
      for(auto s : wek[x])
            if(vis[s] == 0)
                  dfs(s);
      stos.push(x);
}

void dfs2(int x)
{
      skl[x] = odp;
      for(auto s : odw[x])
            if(skl[s] == 0)
                  dfs2(s);
}

int main()
{
      _upgrade
      int n, m;
      cin>>n>>m;
      n = (1<<n) - 1;
      int num = n + 1;
      for(int i = 0 ; i < m;i++)
      {
            int a;
            cin>>a;
            odw[num].pb(a);
            wek[a].pb(num);
            wek[num].pb(n ^ a);
            odw[n ^ a].pb(num);
            num++;
      }

      for(int i = 0 ;i <= n;i++)
      {
            for(int j = 0 ;(1<<j) <= n;j++)
                  if((1<<j) & i)
                        wek[i].pb(i ^ (1<<j)), odw[i ^ ( 1<<j)].pb(i);
      }
      // for(int i = 0 ; i< num;i++)
      // {
      //       cerr<<i<<endl;
      //       for(auto s : wek[i])
      //             cerr<<s<<" ";
      //       cerr<<endl;
      // }

      for(int i = 0 ;i < num;i++)
            if(vis[i] == 0)
                  dfs(i);
      while(SZ(stos))
      {
            int a = stos.top();
            stos.pop();
            if(skl[a] == 0)
            {
                  odp++;
                  dfs2(a);
            }
      }
      set<int> zb;
      for(int i = n + 1;i < num;i++)
            zb.insert(skl[i]);
      cout<<SZ(zb);
      return 0;
}


#include<bits/stdc++.h>
#define pb push_back
#define mp make_pair
#define SZ(x) ((int)(x).size())
#define ALL(x) x.begin(),x.end()
#define fi first
#define se second
#define _upgrade ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);

using namespace std;

typedef long long LL;
typedef pair<int,int> PII;
typedef pair<LL,LL> PLL;
typedef vector<PII> VPII;
typedef vector<PLL> VPLL;
typedef vector<LL> VLL;
typedef vector<int> VI;
typedef vector<string> VS;
typedef vector<char> VC;
typedef long double LD;
typedef pair<LD,LD> PLD;
typedef vector<LD> VLD;
typedef vector<PLD> VPLD;
typedef map<int, int> MII;
typedef map<int, VI> MIVI;
typedef map<LL, LL> MLLLL;
typedef map<LL, VLL> MLLVLL;

template<typename T>
void dbg(T a)
{
      #ifdef LOCAL
            cerr<<a<<"\n";
      #endif
}

template<typename T, typename ...Arg>
void dbg(T a,Arg ...arg)
{
      #ifdef LOCAL
            cerr<<a<<" ";
            dbg(arg...);
      #endif
}

const int maxn = (1<<23);
const int inf = (1e9)+7;
const LL LLinf = (1e18)+7;
const LD eps = 1e-9;
const LL mod = 1e9+7;

// ***************************** CODE ***************************** //

int odp = 1;
VI wek[maxn], odw[maxn];
bool vis[maxn];
int skl[maxn];
stack<int> stos;

void dfs(int x)
{
      vis[x] = 1;
      for(auto s : wek[x])
            if(vis[s] == 0)
                  dfs(s);
      stos.push(x);
}

void dfs2(int x)
{
      skl[x] = odp;
      for(auto s : odw[x])
            if(skl[s] == 0)
                  dfs2(s);
}

int main()
{
      _upgrade
      int n, m;
      cin>>n>>m;
      n = (1<<n) - 1;
      int num = n + 1;
      for(int i = 0 ; i < m;i++)
      {
            int a;
            cin>>a;
            odw[num].pb(a);
            wek[a].pb(num);
            wek[num].pb(n ^ a);
            odw[n ^ a].pb(num);
            num++;
      }

      for(int i = 0 ;i <= n;i++)
      {
            for(int j = 0 ;(1<<j) <= n;j++)
                  if((1<<j) & i)
                        wek[i].pb(i ^ (1<<j)), odw[i ^ ( 1<<j)].pb(i);
      }
      // for(int i = 0 ; i< num;i++)
      // {
      //       cerr<<i<<endl;
      //       for(auto s : wek[i])
      //             cerr<<s<<" ";
      //       cerr<<endl;
      // }

      for(int i = 0 ;i < num;i++)
            if(vis[i] == 0)
                  dfs(i);
      while(SZ(stos))
      {
            int a = stos.top();
            stos.pop();
            if(skl[a] == 0)
            {
                  odp++;
                  dfs2(a);
            }
      }
      set<int> zb;
      for(int i = n + 1;i < num;i++)
            zb.insert(skl[i]);
      cout<<SZ(zb);
      return 0;
}


#include<bits/stdc++.h>
#define pb push_back
#define mp make_pair
#define SZ(x) ((int)(x).size())
#define ALL(x) x.begin(),x.end()
#define fi first
#define se second
#define _upgrade ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);

using namespace std;

typedef long long LL;
typedef pair<int,int> PII;
typedef pair<LL,LL> PLL;
typedef vector<PII> VPII;
typedef vector<PLL> VPLL;
typedef vector<LL> VLL;
typedef vector<int> VI;
typedef vector<string> VS;
typedef vector<char> VC;
typedef long double LD;
typedef pair<LD,LD> PLD;
typedef vector<LD> VLD;
typedef vector<PLD> VPLD;
typedef map<int, int> MII;
typedef map<int, VI> MIVI;
typedef map<LL, LL> MLLLL;
typedef map<LL, VLL> MLLVLL;

template<typename T>
void dbg(T a)
{
      #ifdef LOCAL
            cerr<<a<<"\n";
      #endif
}

template<typename T, typename ...Arg>
void dbg(T a,Arg ...arg)
{
      #ifdef LOCAL
            cerr<<a<<" ";
            dbg(arg...);
      #endif
}

const int maxn = (1<<23);
const int inf = (1e9)+7;
const LL LLinf = (1e18)+7;
const LD eps = 1e-9;
const LL mod = 1e9+7;

// ***************************** CODE ***************************** //

int odp = 1;
VI wek[maxn], odw[maxn];
bool vis[maxn];
int skl[maxn];
stack<int> stos;
int n, m;

void dfs(int x)
{
      vis[x] = 1;
      for(auto s : wek[x])
            if(vis[s] == 0)
                  dfs(s);
      if(x <= n)
      {
            for(int j = 0 ;(1<<j) <= n;j++)
                  if((1<<j) & x)
                        if(vis[x ^ (1<<j)] == 0)
                              dfs(x ^ (1<<j));
      }
      stos.push(x);
}

void dfs2(int x)
{
      skl[x] = odp;
      for(auto s : odw[x])
            if(skl[s] == 0)
                  dfs2(s);
      if(x <= n)
      {
            for(int j = 0 ;(1<<j) <= n;j++)
                  if(!((1<<j) & x))
                        if(skl[x ^ (1<<j)] == 0)
                              dfs2(x ^ ( 1<<j));
      }
}

int main()
{
      _upgrade
      cin>>n>>m;
      n = (1<<n) - 1;
      int num = n + 1;
      for(int i = 0 ; i < m;i++)
      {
            int a;
            cin>>a;
            odw[num].pb(a);
            wek[a].pb(num);
            wek[num].pb(n ^ a);
            odw[n ^ a].pb(num);
            num++;
      }
      // for(int i = 0 ; i< num;i++)
      // {
      //       cerr<<i<<endl;
      //       for(auto s : wek[i])
      //             cerr<<s<<" ";
      //       cerr<<endl;
      // }

      for(int i = 0 ;i < num;i++)
            if(vis[i] == 0)
                  dfs(i);
      while(SZ(stos))
      {
            int a = stos.top();
            stos.pop();
            if(skl[a] == 0)
            {
                  odp++;
                  dfs2(a);
            }
      }
      set<int> zb;
      for(int i = n + 1;i < num;i++)
            zb.insert(skl[i]);
      cout<<SZ(zb);
      return 0;
}


#include<bits/stdc++.h>
#define pb push_back
#define mp make_pair
#define SZ(x) ((int)(x).size())
#define ALL(x) x.begin(),x.end()
#define fi first
#define se second
#define _upgrade ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);

using namespace std;

typedef long long LL;
typedef pair<int,int> PII;
typedef pair<LL,LL> PLL;
typedef vector<PII> VPII;
typedef vector<PLL> VPLL;
typedef vector<LL> VLL;
typedef vector<int> VI;
typedef vector<string> VS;
typedef vector<char> VC;
typedef long double LD;
typedef pair<LD,LD> PLD;
typedef vector<LD> VLD;
typedef vector<PLD> VPLD;
typedef map<int, int> MII;
typedef map<int, VI> MIVI;
typedef map<LL, LL> MLLLL;
typedef map<LL, VLL> MLLVLL;

template<typename T>
void dbg(T a)
{
      #ifdef LOCAL
            cerr<<a<<"\n";
      #endif
}

template<typename T, typename ...Arg>
void dbg(T a,Arg ...arg)
{
      #ifdef LOCAL
            cerr<<a<<" ";
            dbg(arg...);
      #endif
}

const int maxn = (1<<23);
const int inf = (1e9)+7;
const LL LLinf = (1e18)+7;
const LD eps = 1e-9;
const LL mod = 1e9+7;

// ***************************** CODE ***************************** //

int odp = 1;
bool czy[maxn];
bool vis[maxn];
int gdzie[maxn], skad[maxn];
int skl[maxn];
stack<int> stos;
int n, m;

void dfs(int x)
{
      // dbg(x);
      if(czy[x] == 0)
            return ;
      vis[x] = 1;
      if(x <= n)
      {
            for(int j = 0 ;(1<<j) <= n;j++)
                  if((1<<j) & x)
                        if(vis[x ^ (1<<j)] == 0)
                              dfs(x ^ (1<<j));
      }
      if(gdzie[x] != -1 && vis[gdzie[x]] == 0)
            dfs(gdzie[x]);
      stos.push(x);
}

void dfs2(int x)
{
      // dbg(x);
      if(czy[x] == 0)
            return ;
      skl[x] = odp;
      if(x <= n)
      {
            for(int j = 0 ;(1<<j) <= n;j++)
                  if(!((1<<j) & x))
                        if(skl[x ^ (1<<j)] == 0)
                              dfs2(x ^ ( 1<<j));
                               // dbg(x, x ^ ( 1<<j));
      }
      if(skad[x] != -1 && skl[skad[x]] == 0)
            dfs2(skad[x]);
}

int main()
{
      _upgrade
      cin>>n>>m;
      n = (1<<n) - 1;
      for(int i = 0 ;i <= 2 * n + 1;i++)
            skad[i] = gdzie[i] = -1;
      for(int i = 0 ; i < m;i++)
      {
            int a;
            cin>>a;
            czy[a + n + 1] = 1;
            gdzie[a + n + 1] = a ^ n;
            // dbg(a + n + 1, a ^ n );
            // dbg(a, a + n + 1);
            skad[a ^ n] = a + n + 1;
            skad[a + n + 1] = a;
            gdzie[a] = a + n + 1;
      }
      for(int i = 0 ;i <= n;i++)
            czy[i] = 1;
      for(int i = 0 ;i <= 2 * n + 1;i++)
            if(czy[i] == 1 && vis[i] == 0)
                  dfs(i);
      while(SZ(stos))
      {
            int a = stos.top();
            stos.pop();
            if(skl[a] == 0)
            {
                  odp++;
                  // dbg("#");
                  dfs2(a);
            }
      }
      set<int> zb;
      for(int i = n + 1;i <= 2 * n + 1;i++)
            if(czy[i] == 1)
                  zb.insert(skl[i]);
      cout<<SZ(zb);
      return 0;
}


#include<bits/stdc++.h>
#define rep(i,l,r) for(int i=l;i<r;i++)
#define put(x) cout<<#x<<" = "<<x<<endl;
#define X first
#define Y second
#define pb push_back
#define pp pop_back
#pragma GCC optimize("O2")
using namespace std;
typedef long long num;
typedef pair<int,int> point;
const int maxn=2e5+10;

int n,k;
vector<int> G[maxn];
int32_t main(){
    scanf("%d",&n);
    rep(i,1,n){
	int a,b;
	scanf("%d%d",&a,&b);
	a--,b--;
	G[a].pb(b);
	G[b].pb(a);
    }
    int root=-1;
    vector<int> lf;
    rep(a,0,n){
	if(int(G[a].size())>2){
	    if(root==-1){
		root=a+1;
	    }else{
		printf("No\n");
		return 0;
	    }
	}
	if(int(G[a].size())==1){
	    lf.pb(a+1);
	}
    }
    printf("Yes\n");
    if(root==-1){
	printf("1\n%d %d\n",lf[0],lf[1]);
	return 0;
    }else{
	printf("%d\n",int(lf.size()));
	for(int x:lf){
	    printf("%d %d\n",x,root);
	}
    }
}


#include<bits/stdc++.h>
#define rep(i,l,r) for(int i=l;i<r;i++)
#define put(x) cout<<#x<<" = "<<x<<endl;
#define X first
#define Y second
#define pb push_back
#define pp pop_back
#pragma GCC optimize("O2")
using namespace std;
typedef long long num;
typedef pair<int,int> point;
const int maxn=23,maxm=1<<maxn;

int n,m,A[maxm];
int mark[maxm];
inline bool bit(int x,int pos){
    return ((x>>pos)&1);
}

struct DSU{
    int par[maxm];
    int cm;
    DSU(){
	fill(par,par+maxm,-1);
    }
    int root(int x){
	return par[x]<0?x:par[x]=root(par[x]);
    }
    void merge(int x,int y){
	x=root(x);
	y=root(y);
	if(x==y) return;
	cm--;
	if(-par[x]<-par[y]) swap(x,y);
	par[x]+=par[y];
	par[y]=x;
    }
}dsu;

int cc=0;
int add(int id,int x,int pos=0){
    if(mark[x]){
	if(mark[x]!=-1){
	    dsu.merge(mark[x],id);
	    cc++;
	}
	return mark[x];
    }
    if(pos==n){
	return -1;
    }
    int dd=add(id,x,pos+1);
    mark[x]=dd;
    if(bit(x,pos)==1){
	x^=(1<<pos);
	int cd=add(id,x,pos+1);
	mark[x]=cd;
	return max(cd,dd);
    }
    return dd;
}

int32_t main(){
    scanf("%d%d",&n,&m);
    dsu.cm=m;
    rep(i,0,m){
	scanf("%d",A+i);
    }
    int M=(1<<n)-1;
    rep(i,0,m){
	mark[A[i]]=i+1;
    }
    rep(i,0,m){
	cc=0;
	add(i+1,M^A[i]);
    }
    printf("%d\n",dsu.cm);
}


#include<bits/stdc++.h>
#define rep(i,l,r) for(int i=l;i<r;i++)
#define put(x) cout<<#x<<" = "<<x<<endl;
#define X first
#define Y second
#define pb push_back
#define pp pop_back
#pragma GCC optimize("O2")
using namespace std;
typedef long long num;
typedef pair<int,int> point;
const int maxn=23,maxm=1<<maxn;

int n,m,A[maxm];
int mark[maxm];
inline bool bit(int x,int pos){
    return ((x>>pos)&1);
}

struct DSU{
    int par[maxm];
    int cm;
    DSU(){
	fill(par,par+maxm,-1);
    }
    int root(int x){
	return par[x]<0?x:par[x]=root(par[x]);
    }
    void merge(int x,int y){
	x=root(x);
	y=root(y);
	if(x==y) return;
	cm--;
	if(-par[x]<-par[y]) swap(x,y);
	par[x]+=par[y];
	par[y]=x;
    }
}dsu;

int cc=0;
int add(int id,int x,int pos=0){
    if(mark[x]){
	if(mark[x]!=-1){
	    dsu.merge(mark[x],id);
	    cc++;
	}
	return mark[x];
    }
    if(pos==n){
	return -1;
    }
    int dd=add(id,x,pos+1);
    if(dd>0) mark[x]=dd;
    if(bit(x,pos)==1){
	x^=(1<<pos);
	int cd=add(id,x,pos+1);
	if(cd>0) mark[x]=cd;
	return max(cd,dd);
    }
    return dd;
}

int32_t main(){
    scanf("%d%d",&n,&m);
    dsu.cm=m;
    rep(i,0,m){
	scanf("%d",A+i);
    }
    int M=(1<<n)-1;
    rep(i,0,m){
	mark[A[i]]=i+1;
    }
    rep(i,0,m){
	cc=0;
	add(i+1,M^A[i]);
    }
    printf("%d\n",dsu.cm);
}


#include<bits/stdc++.h>
#define rep(i,l,r) for(int i=l;i<r;i++)
#define put(x) cout<<#x<<" = "<<x<<endl;
#define X first
#define Y second
#define pb push_back
#define pp pop_back
#pragma GCC optimize("O2")
using namespace std;
typedef long long num;
typedef pair<int,int> point;
const int maxn=23,maxm=1<<maxn;

int n,m,A[maxm];
int mark[maxm];
inline bool bit(int x,int pos){
    return ((x>>pos)&1);
}

struct DSU{
    int par[maxm];
    int cm;
    DSU(){
	fill(par,par+maxm,-1);
    }
    int root(int x){
	return par[x]<0?x:par[x]=root(par[x]);
    }
    void merge(int x,int y){
	x=root(x);
	y=root(y);
	if(x==y) return;
	cm--;
	if(-par[x]<-par[y]) swap(x,y);
	par[x]+=par[y];
	par[y]=x;
    }
}dsu;

int cc=0;
void add(int id,int x,int pos=0){
    if(mark[x]){
	if(mark[x]!=-1){
	    dsu.merge(mark[x],id);
	    cc++;
	}
	return;
    }
    if(pos==n){
	return;
    }
    add(id,x,pos+1);
    if(bit(x,pos)==1){
	x^=(1<<pos);
	add(id,x,pos+1);
    }
}

void add2(int id,int x,int pos=0){
    if(mark[x]){
	return;
    }
    if(pos==n){
	mark[x]=id;
	return;
    }
    add2(id,x,pos+1);
    if(bit(x,pos)==1){
	x^=(1<<pos);
	add2(id,x,pos+1);
    }
}
int32_t main(){
    scanf("%d%d",&n,&m);
    dsu.cm=m;
    rep(i,0,m){
	scanf("%d",A+i);
    }
    int M=(1<<n)-1;
    rep(i,0,m){
	mark[A[i]]=i+1;
    }
    rep(i,0,m){
	cc=0;
	add(i+1,M^A[i]);
	add2(cc?i+1:-1,M^A[i]);
    }
    printf("%d\n",dsu.cm);
}


#include<bits/stdc++.h>
#define rep(i,l,r) for(int i=l;i<r;i++)
#define put(x) cout<<#x<<" = "<<x<<endl;
#define X first
#define Y second
#define pb push_back
#define pp pop_back
#pragma GCC optimize("O2")
using namespace std;
typedef long long num;
typedef pair<int,int> point;
const int maxn=23,maxm=1<<maxn;

int n,m,A[maxm];
int mark[maxm];
inline bool bit(int x,int pos){
    return ((x>>pos)&1);
}

struct DSU{
    int par[maxm];
    int cm;
    DSU(){
	fill(par,par+maxm,-1);
    }
    int root(int x){
	return par[x]<0?x:par[x]=root(par[x]);
    }
    void merge(int x,int y){
	x=root(x);
	y=root(y);
	if(x==y) return;
	cm--;
	if(-par[x]<-par[y]) swap(x,y);
	par[x]+=par[y];
	par[y]=x;
    }
}dsu;

int cc=0;
int add(int id,int x){
    if(mark[x]){
	if(mark[x]!=-1){
	    dsu.merge(mark[x],id);
	    cc++;
	}
	return mark[x];
    }
    mark[x]=-1;
    rep(i,0,n){
	if(bit(x,i)){
	    int y=add(id,x^(1<<i));
	    if(y!=-1){
		mark[x]=y;
	    }
	}
    }
    return mark[x];
}

int32_t main(){
    scanf("%d%d",&n,&m);
    dsu.cm=m;
    rep(i,0,m){
	scanf("%d",A+i);
    }
    int M=(1<<n)-1;
    rep(i,0,m){
	mark[A[i]]=i+1;
    }
    rep(i,0,m){
	cc=0;
	add(i+1,M^A[i]);
    }
    printf("%d\n",dsu.cm);
}


#include<bits/stdc++.h>
#define rep(i,l,r) for(int i=l;i<r;i++)
#define put(x) cout<<#x<<" = "<<x<<endl;
#define X first
#define Y second
#define pb push_back
#define pp pop_back
#pragma GCC optimize("O2")
using namespace std;
typedef long long num;
typedef pair<int,int> point;
const int maxn=23,maxm=1<<maxn;

int n,m,A[maxm];
int mark[maxm];
inline bool bit(int x,int pos){
    return ((x>>pos)&1);
}

struct DSU{
    int par[maxm];
    int cm;
    DSU(){
	fill(par,par+maxm,-1);
    }
    int root(int x){
	return par[x]<0?x:par[x]=root(par[x]);
    }
    void merge(int x,int y){
	x=root(x);
	y=root(y);
	if(x==y) return;
	cm--;
	if(-par[x]<-par[y]) swap(x,y);
	par[x]+=par[y];
	par[y]=x;
    }
}dsu;

int cc=0;
int add(int id,int x){
    if(mark[x]){
	if(mark[x]!=-1){
	    dsu.merge(mark[x],id);
	    cc++;
	}
	return mark[x];
    }
    mark[x]=-1;
    rep(i,0,n){
	if(bit(x,i)){
	    int y=add(id,x^(1<<i));
	    if(y!=-1){
		mark[x]=y;
	    }
	}
    }
    return mark[x];
}

int32_t main(){
    scanf("%d%d",&n,&m);
    n++;
    dsu.cm=m;
    rep(i,0,m){
	scanf("%d",A+i);
    }
    int M=(1<<n)-1;
    rep(i,0,m){
	mark[A[i]]=i+1;
    }
    rep(i,0,m){
	cc=0;
	add(i+1,M^A[i]);
    }
    printf("%d\n",dsu.cm);
}


#include<bits/stdc++.h>
#define rep(i,l,r) for(int i=l;i<r;i++)
#define put(x) cout<<#x<<" = "<<x<<endl;
#define X first
#define Y second
#define pb push_back
#define pp pop_back
#pragma GCC optimize("O2")
using namespace std;
typedef long long num;
typedef pair<int,int> point;
const int maxn=23,maxm=1<<maxn;

int n,m,A[maxm];
int mark[maxm];
inline bool bit(int x,int pos){
    return ((x>>pos)&1);
}

struct DSU{
    int par[maxm];
    int cm;
    DSU(){
	fill(par,par+maxm,-1);
    }
    int root(int x){
	return par[x]<0?x:par[x]=root(par[x]);
    }
    void merge(int x,int y){
	x=root(x);
	y=root(y);
	if(x==y) return;
	cm--;
	if(-par[x]<-par[y]) swap(x,y);
	par[x]+=par[y];
	par[y]=x;
    }
}dsu;

int cc=0;
int add(int id,int x){
    if(mark[x]){
	if(mark[x]!=-1){
	    dsu.merge(mark[x],id);
	    cc++;
	}
	return mark[x];
    }
    mark[x]=-1;
    rep(i,0,maxn){
	if(bit(x,i)){
	    int y=add(id,x^(1<<i));
	    if(y!=-1){
		mark[x]=y;
		dsu.merge(mark[x],id);
	    }
	}
    }
    return mark[x];
}

int32_t main(){
    scanf("%d%d",&n,&m);
    dsu.cm=m;
    rep(i,0,m){
	scanf("%d",A+i);
    }
    int M=(1<<n)-1;
    rep(i,0,m){
	mark[A[i]]=i+1;
    }
    rep(i,0,m){
	cc=0;
	add(i+1,M^A[i]);
    }
    printf("%d\n",dsu.cm);
}


#include<bits/stdc++.h>
#define rep(i,l,r) for(int i=l;i<r;i++)
#define put(x) cout<<#x<<" = "<<x<<endl;
#define X first
#define Y second
#define pb push_back
#define pp pop_back
#pragma GCC optimize("O2")
using namespace std;
typedef long long num;
typedef pair<int,int> point;
const int maxn=23,maxm=1<<maxn;

int n,m,A[maxm];
int mark[maxm];
inline bool bit(int x,int pos){
    return ((x>>pos)&1);
}

struct DSU{
    int par[maxm];
    int cm;
    DSU(){
	fill(par,par+maxm,-1);
    }
    int root(int x){
	return par[x]<0?x:par[x]=root(par[x]);
    }
    void merge(int x,int y){
	x=root(x);
	y=root(y);
	if(x==y) return;
	cm--;
	if(-par[x]<-par[y]) swap(x,y);
	par[x]+=par[y];
	par[y]=x;
    }
}dsu;

int cc=0;
void add(int id,int x,int pos=0){
    if(mark[x]){
	dsu.merge(mark[x],id);
	cc++;
	return;
    }
    if(pos==n){
	return;
    }
    add(id,x,pos+1);
    if(bit(x,pos)==1){
	x^=(1<<pos);
	add(id,x,pos+1);
    }
}

void add2(int id,int x,int pos=0){
    if(mark[x]){
	return;
    }
    if(pos==n){
	mark[x]=id;
	return;
    }
    add2(id,x,pos+1);
    if(bit(x,pos)==1){
	x^=(1<<pos);
	add2(id,x,pos+1);
    }
}
int32_t main(){
    scanf("%d%d",&n,&m);
    dsu.cm=m;
    rep(i,0,m){
	scanf("%d",A+i);
    }
    int M=(1<<n)-1;
    rep(i,0,m){
	mark[A[i]]=i+1;
    }
    rep(i,0,m){
	cc=0;
	add(i+1,M^A[i]);
	if(cc){
	    add2(i+1,M^A[i]);
	}
    }
    printf("%d\n",dsu.cm);
}


#include<bits/stdc++.h>
using namespace std;
int a[(1<<22)+10];
int v[(1<<22)+10];
int n,k,m;
int getbit(int x,int i){
    return (x>>i)&1;
}
void dfs(int x,int c){
    if(x==0)return ;
    if(v[x]>0)return ;
    if(v[x]==0)v[x]=c;

    //cout<<t<<endl;
    for(int i=0;i<n;i++){
        int tmp,tt=x-(getbit(x,i)<<i);
        //cout<<tt<<endl;
        if(v[tt]!=-1&&v[tt])continue;
        tmp=v[tt];
        v[tt]=c;
        dfs(tt,c);
        if(tmp!=0)v[tt]=tmp;
        else /*if(v[(1<<n)-tt-1])*/dfs((1<<n)-tt-1,c);
    }
}
int main(){
    memset(v,-1,sizeof(v));
    cin>>n>>k;
    for(int i=1;i<=k;i++){
        scanf("%d",&a[i]);
        v[a[i]]=0;
    }
    sort(a+1,a+1+k);
    int c=1;
    for(int i=1;i<=k;i++){
        if(!v[a[i]]){
            v[a[i]]=c;
            dfs((1<<n)-a[i]-1,c);
            c++;
        }
    }

    /*for(int i=1;i<=k;i++){
        cout<<a[i]<<' '<<v[a[i]]<<endl;
    }*/
    printf("%d\n",c-1);
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
int a[(1<<22)+10];
int v[(1<<22)+10];
int n,k,m;
int getbit(int x,int i){
    return (x>>i)&1;
}
void dfs(int x,int c){
    if(x==0)return ;
    if(v[x]==0)v[x]=c;
    //cout<<t<<endl;
    for(int i=0;i<n;i++){
        int tmp,tt=x-(getbit(x,i)<<i);
        //cout<<tt<<endl;
        if(v[tt]!=-1&&v[tt])continue;
        tmp=v[tt];
        v[tt]=c;
        dfs(tt,c);
        if(tmp!=0)v[tt]=tmp;
        else /*if(v[(1<<n)-tt-1])*/dfs((1<<n)-tt-1,c);
    }
}
int main(){
    memset(v,-1,sizeof(v));
    cin>>n>>k;
    for(int i=1;i<=k;i++){
        scanf("%d",&a[i]);
        v[a[i]]=0;
    }
    sort(a+1,a+1+k);
    int c=1;
    for(int i=1;i<=k;i++){
        if(!v[a[i]]){
            v[a[i]]=c;
            dfs((1<<n)-a[i]-1,c);
            c++;
        }
    }

    for(int i=1;i<=k;i++){
        cout<<a[i]<<' '<<v[a[i]]<<endl;
    }
    printf("%d\n",c-1);
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
int a[(1<<22)+10];
int v[(1<<22)+10];
int n,k,m;
int getbit(int x,int i){
    return (x>>i)&1;
}
void dfs(int x,int c){
    int t=0;
    for(int i=0;i<n;i++){
        t+=((1^getbit(x,i))<<i);
    }
    if(v[t]==0)v[t]=c;
    //cout<<t<<endl;
    for(int i=0;i<n;i++){
        int tmp,tt=t-(getbit(t,i)<<i);
        //cout<<tt<<endl;
        tmp=v[tt];
        if(v[tt])continue;
        v[tt]=c;
        dfs(tt,c);
        if(tmp!=0)v[tt]=tmp;
    }
}
int main(){
    memset(v,-1,sizeof(v));
    cin>>n>>k;
    for(int i=1;i<=k;i++){
        scanf("%d",&a[i]);
        v[a[i]]=0;
    }
    sort(a+1,a+1+k);
    int c=1;
    for(int i=1;i<=k;i++){
        if(!v[a[i]]){
            dfs(a[i],c);
            c++;
        }
    }

    /*for(int i=1;i<=k;i++){
        printf("%d\n",v[a[i]]);
    }*/
    printf("%d\n",c-1);
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
int a[(1<<22)+10];
int v[(1<<22)+10];
int n,k,m;
int getbit(int x,int i){
    return (x>>i)&1;
}
void dfs(int x,int c){
    int t=0;
    for(int i=0;i<n;i++){
        t+=((1^getbit(x,i))<<i);
    }
    //cout<<t<<endl;
    for(int i=0;i<n;i++){
        int tmp,tt=t-(getbit(t,i)<<i);
        //cout<<tt<<endl;
        tmp=v[tt];
        if(v[tt])continue;
        v[tt]=c;
        dfs(tt,c);
        if(tmp!=0)v[tt]=tmp;
    }
}
int main(){
    memset(v,-1,sizeof(v));
    cin>>n>>k;
    for(int i=1;i<=k;i++){
        scanf("%d",&a[i]);
        v[a[i]]=0;
    }
    sort(a+1,a+1+k);
    int c=1;
    for(int i=1;i<=k;i++){
        if(!v[a[i]]){
            dfs(a[i],c);
            c++;
        }
    }

    /*for(int i=1;i<=k;i++){
        printf("%d\n",v[a[i]]);
    }*/
    printf("%d\n",c-1);
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
int a[(1<<22)+10];
int v[(1<<22)+10];
int n,k,m;
int getbit(int x,int i){
    return (x>>i)&1;
}
void dfs(int x,int c){
    if(x==0)return ;
    if(v[x]==0)v[x]=c;
    if(v[x]>0)return ;
    //cout<<t<<endl;
    for(int i=0;i<n;i++){
        int tmp,tt=x-(getbit(x,i)<<i);
        //cout<<tt<<endl;
        if(v[tt]!=-1&&v[tt])continue;
        tmp=v[tt];
        v[tt]=c;
        dfs(tt,c);
        if(tmp!=0)v[tt]=tmp;
        else /*if(v[(1<<n)-tt-1])*/dfs((1<<n)-tt-1,c);
    }
}
int main(){
    memset(v,-1,sizeof(v));
    cin>>n>>k;
    for(int i=1;i<=k;i++){
        scanf("%d",&a[i]);
        v[a[i]]=0;
    }
    sort(a+1,a+1+k);
    int c=1;
    for(int i=1;i<=k;i++){
        if(!v[a[i]]){
            v[a[i]]=c;
            dfs((1<<n)-a[i]-1,c);
            c++;
        }
    }

    /*for(int i=1;i<=k;i++){
        cout<<a[i]<<' '<<v[a[i]]<<endl;
    }*/
    printf("%d\n",c-1);
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
int a[(1<<22)+10];
int v[(1<<22)+10];
int n,k,m;
int getbit(int x,int i){
    return (x>>i)&1;
}
void dfs(int x,int c){
    if(x==0)return ;
    if(v[x]==0)v[x]=c;
    //cout<<t<<endl;
    for(int i=0;i<n;i++){
        int tmp,tt=x-(getbit(x,i)<<i);
        //cout<<tt<<endl;
        if(v[tt]!=-1&&v[tt])continue;
        tmp=v[tt];
        v[tt]=c;
        dfs(tt,c);
        if(tmp!=0)v[tt]=tmp;
        else /*if(v[(1<<n)-tt-1])*/dfs((1<<n)-tt-1,c);
    }
}
int main(){
    memset(v,-1,sizeof(v));
    cin>>n>>k;
    for(int i=1;i<=k;i++){
        scanf("%d",&a[i]);
        v[a[i]]=0;
    }
    sort(a+1,a+1+k);
    int c=1;
    for(int i=1;i<=k;i++){
        if(!v[a[i]]){
            v[a[i]]=c;
            dfs((1<<n)-a[i]-1,c);
            c++;
        }
    }

    /*for(int i=1;i<=k;i++){
        cout<<a[i]<<' '<<v[a[i]]<<endl;
    }*/
    printf("%d\n",c-1);
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
int a[(1<<22)+10];
int v[(1<<22)+10];
int n,k,m;
int getbit(int x,int i){
    return (x>>i)&1;
}
void dfs(int x,int c){
    if(x==0)return ;
    if(v[x]==0)v[x]=c;

    //cout<<t<<endl;
    for(int i=0;i<n;i++){
        int tmp,tt=x-(getbit(x,i)<<i);
        //cout<<tt<<endl;
        if(v[tt]!=-1&&v[tt])continue;
        tmp=v[tt];
        v[tt]=c;
        dfs(tt,c);
        if(tmp!=0)v[tt]=tmp;
        else if(v[(1<<n)-tt-1]<=0)dfs((1<<n)-tt-1,c);
    }
}
int main(){
    memset(v,-1,sizeof(v));
    cin>>n>>k;
    for(int i=1;i<=k;i++){
        scanf("%d",&a[i]);
        v[a[i]]=0;
    }
    sort(a+1,a+1+k);
    int c=1;
    for(int i=1;i<=k;i++){
        if(!v[a[i]]){
            v[a[i]]=c;
            dfs((1<<n)-a[i]-1,c);
            c++;
        }
    }

    /*for(int i=1;i<=k;i++){
        cout<<a[i]<<' '<<v[a[i]]<<endl;
    }*/
    printf("%d\n",c-1);
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
int a[(1<<22)+10];
int v[(1<<22)+10];
int n,k,m;
int getbit(int x,int i){
    return (x>>i)&1;
}
void dfs(int x,int c){
    if(x==0)return ;
    if(v[x]==0)v[x]=c;

    //cout<<t<<endl;
    for(int i=0;i<n;i++){
        int tmp,tt=x-(getbit(x,i)<<i);
        //cout<<tt<<endl;
        if(v[tt]!=-1&&v[tt])continue;
        tmp=v[tt];
        v[tt]=c;
        dfs(tt,c);
        if(tmp!=0)v[tt]=-2;
        else if(v[(1<<n)-tt-1]==-1||v[(1<<n)-tt-1]==0)dfs((1<<n)-tt-1,c);
    }
}
int main(){
    memset(v,-1,sizeof(v));
    cin>>n>>k;
    for(int i=1;i<=k;i++){
        scanf("%d",&a[i]);
        v[a[i]]=0;
    }
    sort(a+1,a+1+k);
    int c=1;
    for(int i=1;i<=k;i++){
        if(!v[a[i]]){
            v[a[i]]=c;
            dfs((1<<n)-a[i]-1,c);
            c++;
        }
    }

    /*for(int i=1;i<=k;i++){
        cout<<a[i]<<' '<<v[a[i]]<<endl;
    }*/
    printf("%d\n",c-1);
    return 0;
}


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cctype>
#include<cstring>
#include<cmath>
using namespace std;
inline int read(){
	int w=0,x=0;char c=getchar();
	while(!isdigit(c))w|=c=='-',c=getchar();
	while(isdigit(c))x=x*10+(c^48),c=getchar();
	return w?-x:x;
}
namespace star
{
	const int maxn=23,maxm=5e6;
	bool vis[maxm],is[maxm];
	int n,m,a[maxm];
	void dfs(int x){
		vis[x]=1;
		if(is[x] and !vis[((1<<n)-1)^x]) dfs(((1<<n)-1)^x);
		for(int i=0;i<n;i++)
			if((x>>i)&1 and !vis[x^(1<<i)])dfs(x^(1<<i));
	}
	inline void work(){
		n=read(),m=read();
		int ans=0;
		for(int i=1;i<=m;i++) a[i]=read(),is[a[i]]=1;
		if(is[0])return puts("1"),void();
		for(int i=1;i<=m;i++) if(!vis[a[i]]) vis[a[i]]=1,ans++,dfs(((1<<n)-1)^a[i]);
		printf("%d\n",ans);
	}
}
signed main(){
	star::work();
	return 0;
}


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cctype>
#include<cstring>
#include<cmath>
using namespace std;
inline int read(){
	int w=0,x=0;char c=getchar();
	while(!isdigit(c))w|=c=='-',c=getchar();
	while(isdigit(c))x=x*10+(c^48),c=getchar();
	return w?-x:x;
}
namespace star
{
	const int maxn=23,maxm=5e6;
	bool vis[maxm],is[maxm];
	int n,m,a[maxm];
	inline void work(){
		n=read(),m=read();
		int ans=0;
		for(int i=1;i<=m;i++) a[i]=read(),is[a[i]]=1;
		for(int j=1;j<=m;j++){
			if(!vis[a[j]])ans++;
			vis[a[j]]=1;
			int x=((1<<n)-1)^a[j];
			if(!vis[x])for(int i=x;i;i=x&(i-1))
				vis[i]=1;
		}
		printf("%d\n",ans);
	}
}
signed main(){
	star::work();
	return 0;
}


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cctype>
#include<cstring>
#include<cmath>
using namespace std;
inline int read(){
	int w=0,x=0;char c=getchar();
	while(!isdigit(c))w|=c=='-',c=getchar();
	while(isdigit(c))x=x*10+(c^48),c=getchar();
	return w?-x:x;
}
namespace star
{
	const int maxn=23,maxm=5e6;
	bool vis[maxm],is[maxm];
	int fa[maxm],n,m,a[maxm];
	int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
	inline void onion(int x,int y){
		x=find(x),y=find(y);
		if(x!=y)
			fa[x]=y;
	}
	inline void work(){
		n=read(),m=read();
		for(int i=1;i<=m;i++) a[i]=read(),fa[a[i]]=a[i],is[a[i]]=1;
		for(int j=1;j<=m;j++){
			int x=((1<<n)-1)^a[j];
			for(int i=x;i;i=x&(i-1))if(is[i]){
				onion(i,a[j]);
				if(vis[i])break;
				vis[i]=1;
			}
		}
		int ans=0;
		for(int i=1;i<=m;i++) if(find(a[i])==a[i]) ans++;
		printf("%d\n",ans);
	}
}
signed main(){
	star::work();
	return 0;
}


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cctype>
#include<cstring>
#include<cmath>
using namespace std;
inline int read(){
	int w=0,x=0;char c=getchar();
	while(!isdigit(c))w|=c=='-',c=getchar();
	while(isdigit(c))x=x*10+(c^48),c=getchar();
	return w?-x:x;
}
namespace star
{
	const int maxn=23,maxm=5e6;
	bool vis[maxm],is[maxm];
	int fa[maxm],n,m,a[maxm];
	int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
	inline void onion(int x,int y){
		x=find(x),y=find(y);
		if(x!=y)
			fa[x]=y;
	}
	inline void work(){
		n=read(),m=read();
		for(int i=1;i<=m;i++) a[i]=read(),fa[a[i]]=a[i],is[a[i]]=1;
		for(int j=1;j<=m;j++){
			int x=((1<<n)-1)^a[j];
			for(int i=x;i;i=x&(i-1))if(is[i]){
				onion(i,a[j]);
			}
		}
		int ans=0;
		for(int i=1;i<=m;i++) if(find(a[i])==a[i]) ans++;
		printf("%d\n",ans);
	}
}
signed main(){
	star::work();
	return 0;
}


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cctype>
#include<cstring>
#include<cmath>
using namespace std;
inline int read(){
	int w=0,x=0;char c=getchar();
	while(!isdigit(c))w|=c=='-',c=getchar();
	while(isdigit(c))x=x*10+(c^48),c=getchar();
	return w?-x:x;
}
namespace star
{
	const int maxn=23,maxm=5e6;
	bool vis[maxm],is[maxm];
	int n,m,a[maxm];
	inline void work(){
		n=read(),m=read();
		int ans=0;
		for(int i=1;i<=m;i++) a[i]=read(),is[a[i]]=1;
		if(is[0])return puts("1"),void();
		for(int j=1;j<=m;j++){
			bool ok=0;
			if(!vis[a[j]])ok=1;
			vis[a[j]]=1;
			int x=((1<<n)-1)^a[j];
			for(int i=x;i;i=x&(i-1)){
				if(vis[i]==1 and is[i]) ok=0;
				vis[i]=1;
			}
			ans+=ok;
		}
		printf("%d\n",ans);
	}
}
signed main(){
	star::work();
	return 0;
}


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cctype>
#include<cstring>
#include<cmath>
using namespace std;
inline int read(){
	int w=0,x=0;char c=getchar();
	while(!isdigit(c))w|=c=='-',c=getchar();
	while(isdigit(c))x=x*10+(c^48),c=getchar();
	return w?-x:x;
}
namespace star
{
	const int maxn=23,maxm=5e6;
	bool vis[maxm],is[maxm];
	int fa[maxm],n,m,a[maxm];
	int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
	inline void onion(int x,int y){
		x=find(x),y=find(y);
		if(x!=y)
			fa[x]=y;
	}
	inline void work(){
		n=read(),m=read();
		for(int i=1;i<=m;i++) a[i]=read(),fa[a[i]]=a[i],is[a[i]]=1;
		for(int j=1;j<=m;j++){
			int x=((1<<n)-1)^a[j];
			for(int i=x;i;i=x&(i-1))if(is[i]){
				onion(i,a[j]);
				if(vis[i])break;
				vis[i]=1;
			}
		}
		int ans=0;
		for(int i=1;i<=m;i++) if(fa[a[i]]==a[i]) ans++;
		printf("%d\n",ans);
	}
}
signed main(){
	star::work();
	return 0;
}


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cctype>
#include<cstring>
#include<cmath>
using namespace std;
inline int read(){
	int w=0,x=0;char c=getchar();
	while(!isdigit(c))w|=c=='-',c=getchar();
	while(isdigit(c))x=x*10+(c^48),c=getchar();
	return w?-x:x;
}
namespace star
{
	const int maxn=23,maxm=5e6;
	bool vis[maxm],is[maxm];
	int n,m,a[maxm];
	void dfs(int x){
		vis[x]=1;
		if(is[x] and !vis[((1<<n)-1)^x]) dfs(((1<<n)-1)^x);
		for(int i=x;i;i=x&(i-1))
			if(!vis[i])dfs(i);
	}
	inline void work(){
		n=read(),m=read();
		int ans=0;
		for(int i=1;i<=m;i++) a[i]=read(),is[a[i]]=1;
		if(is[0])return puts("1"),void();
		for(int i=1;i<=m;i++) if(!vis[a[i]]) vis[a[i]]=1,ans++,dfs(((1<<n)-1)^a[i]);
		printf("%d\n",ans);
	}
}
signed main(){
	star::work();
	return 0;
}


#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=5000005;
int n,m,maxn,ans,cnt;
int head[N],vis[N],a[N];

struct nood {
	int nex,to;
} e[N];

inline void add_edge(int u,int v) {
	e[++cnt].nex=head[u];
	head[u]=cnt;
	e[cnt].to=v;
}

inline void dfs(int u) {
	vis[u]=1;
	for ( int i=head[u];i;i=e[i].nex ) {
		int v=e[i].to;
		if(!vis[v]) dfs(v);
	}
	for ( int i=1;i<=n;i++ )
		if(u&(1<<(i-1))) {
			int now=u^(1<<(i-1));
			if(!vis[now])
				dfs(now);
		}
}

inline int read() {
    int sum=0;char ch=getchar();
    while(!isdigit(ch)) ch=getchar();
    while(isdigit(ch))
        sum=sum*10+(ch^48),ch=getchar();
    return sum;
}

signed main() {
	n=read(),m=read();
	maxn=(1<<n)-1;
	for ( int i=1;i<=m;i++ ) a[i]=read(),add_edge(a[i],a[i]^maxn);
	for ( int i=1;i<=m;i++ )
		if(!vis[a[i]]) {
			vis[a[i]]=1;
			dfs(a[i]^maxn);
			ans++;
		}
	printf("%lld\n",ans);
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
int cnt,n,m,a[5000005],ans,En,head[5000005],vis[5000005];
struct Edge
{
    int next,to;
}E[5000005];
void add(int from,int to)
{
    En++;
    E[En].next=head[from];
    E[En].to=to;
    head[from]=En;//前向星存图
}
void dfs(int k)
{
    vis[k]=1;
    for(int i=head[k];i;i=E[i].next)
    {
        int t=E[i].to;
        if(vis[t]==0)dfs(t);//遍历图
    }
    for(int i=1;i<=n;++i)
    if(k&(1<<(i-1)))
    {
        int t=k^(1<<(i-1));
        if(vis[t]==0)dfs(t);//枚举y每一位
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    cnt=(1<<n)-1;//cnt表示2^(n)-1
    for(int i=1;i<=m;i++)scanf("%d",&a[i]),add(a[i],a[i]^cnt);
    for(int i=1;i<=m;i++)//枚举连通块，累加答案
        if(vis[a[i]]==0)vis[a[i]]=1,dfs(a[i]^cnt),ans++;
    printf("%d\n",ans);//愉快地输出
}


/*
  ------------------------- Hachiikung ---------------------------------
  ---------------------- Worrachate Bosri ------------------------------
  ------ Faculty of Computer Engineering Chulalongkorn University ------
*/
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#include<list>
#include<set>
#include<map>
#include<string>
#include<utility>
using namespace std;
#define REP(i,FN) for(int i=0;i<FN;i++)
#define FOR(i,ST,FN) for(int i=ST;i<=FN;i++)
#define FORD(i,FN,ST) for(int i=FN;i>=ST;i--)
#define FORX(i,c) for(typeof(c.begin())i=c.begin();i!=c.end();i++)
#define pause system("pause")
#define S scanf
#define P printf
#define X first
#define Y second
#define pb push_back
#define PII pair<int,int>
#define mp make_pair
#define sz size()
#define eps 1e-8

const int MOD(1000000007);
const int INF((1<<30)-1);
const int MAXN(205);
const int MAXM(50005);

struct edge
{
    int u,v,g,s;
    bool operator < (const edge &p) const {
        return g < p.g;
    }
}e[MAXM];

multiset<int,greater<int> >b;

PII par[MAXN];

int find_head(int u){
    return (par[u].X==u) ? u : find_head(par[u].X);
}

set<PII>a[MAXN];

void dfs(int node,int p){

    FORX(it,a[node])
     if(it->X != p)
     {
         par[it->X].X=node;
         par[it->X].Y=it->Y;
         dfs(it->X,node);
     }
}

int main(){

    int n,m;
    long long gold,silver;
    cin >> n >> m >> gold >> silver;
    REP(i,m)
     S("%d%d%d%d",&e[i].u,&e[i].v,&e[i].g,&e[i].s);

    sort(e,e+m);

    FOR(i,1,n) par[i].X=i;

    int cnt=0;
    long long ans=-1;

    REP(i,m)
    {
        int u=find_head(e[i].u);
        int v=find_head(e[i].v);

        if(u!=v)
        {
            dfs(e[i].u,-1);
            a[e[i].u].insert(PII(e[i].v,e[i].s));
            a[e[i].v].insert(PII(e[i].u,e[i].s));

            par[e[i].u].X=e[i].v;
            par[e[i].u].Y=i;

            b.insert(e[i].s);

            cnt++;
        }
        else
        {
            bool chk[MAXN]={0};

            int t=e[i].u, lca;
            while(true)
            {
                chk[t]=1;
                if(par[t].X==t) break;
                t=par[t].X;
            }

            t=e[i].v;
            while(true)
            {
                if(chk[t]){ lca=t; break; }
                t=par[t].X;
            }

            t=e[i].u;
            int maxu=-1, idx1;
            while(t!=lca)
            {
                if(e[par[t].Y].s < maxu)
                {
                    maxu=e[par[t].Y].s;
                    idx1=t;
                }
                t=par[t].X;
            }

            t=e[i].v;
            int maxv=-1, idx2;
            while(t!=lca)
            {
                if(e[par[t].Y].s < maxv)
                {
                    maxu=e[par[t].Y].s;
                    idx2=t;
                }
                t=par[t].X;
            }

            if(max(maxu,maxv) > e[i].s)
            {
                if(maxu > maxv)
                {
                    a[idx1].erase(PII(par[idx1].X,par[idx1].Y));
                    a[par[idx1].X].erase(PII(par[idx1].X,par[idx1].Y));

                    b.erase(par[idx1].Y);

                    dfs(e[i].u,-1);
                    a[e[i].u].insert(PII(e[i].v,e[i].s));
                    a[e[i].v].insert(PII(e[i].u,e[i].s));

                    par[e[i].u].X=e[i].v;
                    par[e[i].u].Y=e[i].s;
                }
                else
                {
                    a[idx2].erase(PII(par[idx2].X,par[idx2].Y));
                    a[par[idx2].X].erase(PII(par[idx2].X,par[idx2].Y));

                    b.erase(par[idx2].Y);

                    dfs(e[i].v,-1);
                    a[e[i].u].insert(PII(e[i].v,e[i].s));
                    a[e[i].v].insert(PII(e[i].u,e[i].s));

                    par[e[i].v].X=e[i].u;
                    par[e[i].v].Y=e[i].s;
                }
            }
        }

        if(cnt == n-1)
        {
            if(ans==-1) ans = gold*e[i].g + silver*(*b.begin());
            else ans=min(ans, gold*e[i].g + silver*(*b.begin()));
        }
    }

    cout << ans;
}


/*
  ------------------------- Hachiikung ---------------------------------
  ---------------------- Worrachate Bosri ------------------------------
  ------ Faculty of Computer Engineering Chulalongkorn University ------
*/
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#include<list>
#include<set>
#include<map>
#include<string>
#include<utility>
using namespace std;
#define REP(i,FN) for(int i=0;i<FN;i++)
#define FOR(i,ST,FN) for(int i=ST;i<=FN;i++)
#define FORD(i,FN,ST) for(int i=FN;i>=ST;i--)
#define FORX(i,c) for(typeof(c.begin())i=c.begin();i!=c.end();i++)
#define pause system("pause")
#define S scanf
#define P printf
#define X first
#define Y second
#define pb push_back
#define PII pair<int,int>
#define mp make_pair
#define sz size()
#define eps 1e-8

const int MOD(1000000007);
const int INF((1<<30)-1);
const int MAXN(205);
const int MAXM(50005);

struct edge
{
    int u,v,g,s;
    bool operator < (const edge &p) const {
        return g < p.g;
    }
}e[MAXM];

multiset< int,greater<int> >b;

PII par[MAXN];

int find_head(int u){
    return (par[u].X==u) ? u : find_head(par[u].X);
}

set<PII>a[MAXN];

void dfs(int node,int p){
    FORX(it,a[node])
     if(it->X != p)
     {
         par[it->X].X=node;
         par[it->X].Y=it->Y;
         dfs(it->X,node);
     }
}

int main(){

    int n,m;
    long long gold,silver;
    cin >> n >> m >> gold >> silver;
    REP(i,m)
     S("%d%d%d%d",&e[i].u,&e[i].v,&e[i].g,&e[i].s);

    sort(e,e+m);

    FOR(i,1,n) par[i].X=i;

    int cnt=0;
    long long ans=-1;

    REP(i,m)
    {
        int u=find_head(e[i].u);
        int v=find_head(e[i].v);

        if(u!=v)
        {
            dfs(e[i].u,-1);
            a[e[i].u].insert(PII(e[i].v,e[i].s));
            a[e[i].v].insert(PII(e[i].u,e[i].s));

            par[e[i].u].X=e[i].v;
            par[e[i].u].Y=e[i].s;

            b.insert(e[i].s);

            cnt++;
        }

        else if(e[i].u!=e[i].v)
        {
            bool chk[MAXN]={0};

            int t=e[i].u, lca;
            while(true)
            {
                chk[t]=1;
                if(par[t].X==t) break;
                t=par[t].X;
            }

            t=e[i].v;
            while(true)
            {
                if(chk[t]){ lca=t; break; }
                t=par[t].X;
            }

            t=e[i].u;
            int maxu=-1, idx1=-1;
            while(t!=lca)
            {
                if(par[t].Y > maxu)
                {
                    maxu=par[t].Y;
                    idx1=t;
                }
                t=par[t].X;
            }

            t=e[i].v;
            int maxv=-1, idx2=-1;
            while(t!=lca)
            {
                if(par[t].Y > maxv)
                {
                    maxv=par[t].Y;
                    idx2=t;
                }
                t=par[t].X;
            }

            if(max(maxu,maxv) > e[i].s)
            {
                if(maxu > maxv)
                {
                    a[idx1].erase(PII(par[idx1].X,par[idx1].Y));
                    a[par[idx1].X].erase(PII(idx1,par[idx1].Y));

                    b.erase(par[idx1].Y);
                    b.insert(e[i].s);

                    dfs(e[i].u,-1);
                    a[e[i].u].insert(PII(e[i].v,e[i].s));
                    a[e[i].v].insert(PII(e[i].u,e[i].s));

                    par[e[i].u].X=e[i].v;
                    par[e[i].u].Y=e[i].s;
                }
                else
                {
                    a[idx2].erase(PII(par[idx2].X,par[idx2].Y));
                    a[par[idx2].X].erase(PII(idx2,par[idx2].Y));

                    b.erase(par[idx2].Y);
                    b.insert(e[i].s);

                    dfs(e[i].v,-1);
                    a[e[i].u].insert(PII(e[i].v,e[i].s));
                    a[e[i].v].insert(PII(e[i].u,e[i].s));

                    par[e[i].v].X=e[i].u;
                    par[e[i].v].Y=e[i].s;
                }
            }
        }

        if(cnt == n-1)
        {
            if(ans==-1) ans = gold*e[i].g + silver*(*b.begin());
            else ans=min(ans, gold*e[i].g + silver*(*b.begin()));
        }
    }

    cout << ans;
}


/*
  ------------------------- Hachiikung ---------------------------------
  ---------------------- Worrachate Bosri ------------------------------
  ------ Faculty of Computer Engineering Chulalongkorn University ------
*/
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#include<list>
#include<set>
#include<map>
#include<string>
#include<utility>
using namespace std;
#define REP(i,FN) for(int i=0;i<FN;i++)
#define FOR(i,ST,FN) for(int i=ST;i<=FN;i++)
#define FORD(i,FN,ST) for(int i=FN;i>=ST;i--)
#define FORX(i,c) for(typeof(c.begin())i=c.begin();i!=c.end();i++)
#define pause system("pause")
#define S scanf
#define P printf
#define X first
#define Y second
#define pb push_back
#define PII pair<int,int>
#define mp make_pair
#define sz size()
#define eps 1e-8

const int MOD(1000000007);
const int INF((1<<30)-1);
const int MAXN(205);
const int MAXM(50005);

struct edge
{
    int u,v,g,s;
    bool operator < (const edge &p) const {
        return g < p.g;
    }
}e[MAXM];

multiset< int,greater<int> >b;
multiset< int,greater<int> >::iterator it;

PII par[MAXN];

int find_head(int u){
    return (par[u].X==u) ? u : find_head(par[u].X);
}

set<PII>a[MAXN];

void dfs(int node,int p){
    FORX(it,a[node])
     if(it->X != p)
     {
         par[it->X].X=node;
         par[it->X].Y=it->Y;
         dfs(it->X,node);
     }
}

int main(){

    int n,m;
    long long gold,silver;
    cin >> n >> m >> gold >> silver;
    REP(i,m)
     S("%d%d%d%d",&e[i].u,&e[i].v,&e[i].g,&e[i].s);

    sort(e,e+m);

    FOR(i,1,n) par[i].X=i;

    int cnt=0;
    long long ans=-1;

    REP(i,m)
    {
        int u=find_head(e[i].u);
        int v=find_head(e[i].v);

        if(u!=v)
        {
            dfs(e[i].u,-1);
            a[e[i].u].insert(PII(e[i].v,e[i].s));
            a[e[i].v].insert(PII(e[i].u,e[i].s));

            par[e[i].u].X=e[i].v;
            par[e[i].u].Y=e[i].s;

            b.insert(e[i].s);

            cnt++;
        }

        else if(e[i].u!=e[i].v)
        {
            bool chk[MAXN]={0};

            int t=e[i].u, lca;
            while(true)
            {
                chk[t]=1;
                if(par[t].X==t) break;
                t=par[t].X;
            }

            t=e[i].v;
            while(true)
            {
                if(chk[t]){ lca=t; break; }
                t=par[t].X;
            }

            t=e[i].u;
            int maxu=-1, idx1=-1;
            while(t!=lca)
            {
                if(par[t].Y > maxu)
                {
                    maxu=par[t].Y;
                    idx1=t;
                }
                t=par[t].X;
            }

            t=e[i].v;
            int maxv=-1, idx2=-1;
            while(t!=lca)
            {
                if(par[t].Y > maxv)
                {
                    maxv=par[t].Y;
                    idx2=t;
                }
                t=par[t].X;
            }

            if(max(maxu,maxv) > e[i].s)
            {
                if(maxu > maxv)
                {
                    a[idx1].erase(PII(par[idx1].X,par[idx1].Y));
                    a[par[idx1].X].erase(PII(idx1,par[idx1].Y));

                    it=b.find(par[idx1].Y);
                    b.erase(it);
                    b.insert(e[i].s);

                    dfs(e[i].u,-1);
                    a[e[i].u].insert(PII(e[i].v,e[i].s));
                    a[e[i].v].insert(PII(e[i].u,e[i].s));

                    par[e[i].u].X=e[i].v;
                    par[e[i].u].Y=e[i].s;
                }
                else
                {
                    a[idx2].erase(PII(par[idx2].X,par[idx2].Y));
                    a[par[idx2].X].erase(PII(idx2,par[idx2].Y));

                    it=b.find(par[idx2].Y);
                    b.erase(it);
                    b.insert(e[i].s);

                    dfs(e[i].v,-1);
                    a[e[i].u].insert(PII(e[i].v,e[i].s));
                    a[e[i].v].insert(PII(e[i].u,e[i].s));

                    par[e[i].v].X=e[i].u;
                    par[e[i].v].Y=e[i].s;
                }
            }
        }

        if(cnt == n-1)
        {
            if(ans==-1) ans = gold*e[i].g + silver*(*b.begin());
            else ans=min(ans, gold*e[i].g + silver*(*b.begin()));
        }
    }

    cout << ans;
}


/*
  ------------------------- Hachiikung ---------------------------------
  ---------------------- Worrachate Bosri ------------------------------
  ------ Faculty of Computer Engineering Chulalongkorn University ------
*/
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#include<list>
#include<set>
#include<map>
#include<string>
#include<utility>
using namespace std;
#define REP(i,FN) for(int i=0;i<FN;i++)
#define FOR(i,ST,FN) for(int i=ST;i<=FN;i++)
#define FORD(i,FN,ST) for(int i=FN;i>=ST;i--)
#define FORX(i,c) for(typeof(c.begin())i=c.begin();i!=c.end();i++)
#define pause system("pause")
#define S scanf
#define P printf
#define X first
#define Y second
#define pb push_back
#define PII pair<int,int>
#define mp make_pair
#define sz size()
#define eps 1e-8

const int MOD(1000000007);
const int INF((1<<30)-1);
const int MAXN(205);
const int MAXM(50005);

struct edge
{
    int u,v,g,s;
    bool operator < (const edge &p) const {
        return g < p.g;
    }
}e[MAXM];

multiset< int,greater<int> >b;

PII par[MAXN];

int find_head(int u){
    return (par[u].X==u) ? u : find_head(par[u].X);
}

set<PII>a[MAXN];

void dfs(int node,int p){
    FORX(it,a[node])
     if(it->X != p)
     {
         par[it->X].X=node;
         par[it->X].Y=it->Y;
         dfs(it->X,node);
     }
}

int main(){

    int n,m;
    long long gold,silver;
    cin >> n >> m >> gold >> silver;
    REP(i,m)
     S("%d%d%d%d",&e[i].u,&e[i].v,&e[i].g,&e[i].s);

    sort(e,e+m);

    FOR(i,1,n) par[i].X=i;

    int cnt=0;
    long long ans=-1;

    REP(i,m)
    {
        int u=find_head(e[i].u);
        int v=find_head(e[i].v);

        if(u!=v)
        {
            dfs(e[i].u,-1);
            a[e[i].u].insert(PII(e[i].v,e[i].s));
            a[e[i].v].insert(PII(e[i].u,e[i].s));

            par[e[i].u].X=e[i].v;
            par[e[i].u].Y=e[i].s;

            b.insert(e[i].s);

            cnt++;
        }
        else
        {
            bool chk[MAXN]={0};

            int t=e[i].u, lca;
            while(true)
            {
                chk[t]=1;
                if(par[t].X==t) break;
                t=par[t].X;
            }

            t=e[i].v;
            while(true)
            {
                if(chk[t]){ lca=t; break; }
                t=par[t].X;
            }

            t=e[i].u;
            int maxu=-1, idx1;
            while(t!=lca)
            {
                if(par[t].Y < maxu)
                {
                    maxu=par[t].Y;
                    idx1=t;
                }
                t=par[t].X;
            }

            t=e[i].v;
            int maxv=-1, idx2;
            while(t!=lca)
            {
                if(par[t].Y < maxv)
                {
                    maxu=par[t].Y;
                    idx2=t;
                }
                t=par[t].X;
            }

            if(max(maxu,maxv) > e[i].s)
            {
                if(maxu > maxv)
                {
                    a[idx1].erase(PII(par[idx1].X,par[idx1].Y));
                    a[par[idx1].X].erase(PII(par[idx1].X,par[idx1].Y));

                    b.erase(par[idx1].Y);
                    b.insert(e[i].s);

                    dfs(e[i].u,-1);
                    a[e[i].u].insert(PII(e[i].v,e[i].s));
                    a[e[i].v].insert(PII(e[i].u,e[i].s));

                    par[e[i].u].X=e[i].v;
                    par[e[i].u].Y=e[i].s;
                }
                else
                {
                    a[idx2].erase(PII(par[idx2].X,par[idx2].Y));
                    a[par[idx2].X].erase(PII(par[idx2].X,par[idx2].Y));

                    b.erase(par[idx2].Y);
                    b.insert(e[i].s);

                    dfs(e[i].v,-1);
                    a[e[i].u].insert(PII(e[i].v,e[i].s));
                    a[e[i].v].insert(PII(e[i].u,e[i].s));

                    par[e[i].v].X=e[i].u;
                    par[e[i].v].Y=e[i].s;
                }
            }
        }

        if(cnt == n-1)
        {
            if(ans==-1) ans = gold*e[i].g + silver*(*b.begin());
            else ans=min(ans, gold*e[i].g + silver*(*b.begin()));
        }
    }

    cout << ans;
}


#include <climits>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cctype>
#include <cmath>
#include <algorithm>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <numeric>
#include <string>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <list>
#include <bitset>
using namespace std;

#define ll long long

struct edge{
  int u, v;
  ll g, s;

  bool operator<(const edge &cmp) const{
    return s < cmp.s;
  }
} e[50005], a[50005];

int n, m, cnt, p[205], tam, pu, pv;
ll gt, st;

bool cmpG(edge a, edge b){
  return a.g < b.g;
}

int find(int x){
  if(p[x] == x) return x;
  return p[x] = find(p[x]);
}

ll kruskal(){
  ll res = 0;
  cnt = 0;
  for(int i = 1;i <= n; ++i) p[i] = i;

  sort(a, a + tam);
  for(int i = 0;i < tam; ++i){
    pu = find(a[i].u);
    pv = find(a[i].v);
    if(pu != pv){
      p[pu] = pv;
      res = a[i].s;
      a[cnt++] = a[i];
    }
  }
  tam = cnt;
  return res;
}

int main(){
//  freopen("d.in",  "r", stdin);
//  freopen("d.out", "w", stdout);

  scanf("%d%d", &n, &m);
  scanf("%I64d%I64d", &gt, &st);

  ll res = 1ll<<62, sil;
  cnt = tam = 0;

  for(int i = 0;i < m; ++i){
    scanf("%d%d%I64d%I64d", &e[i].u, &e[i].v, &e[i].g, &e[i].s);
    e[i].g *= gt; e[i].s *= st;
  }

  sort(e, e + m, cmpG);
  for(int i = 0;i < m; ++i){
    a[tam++] = e[i];
    sil = kruskal();
    if(cnt == n - 1){
      sil += e[i].g;
      if(sil < res) res = sil;
    }
  }

  if(res < 1ll<<62) printf("%I64d\n", res);
  else printf("-1\n");
  return 0;
}


#include <climits>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cctype>
#include <cmath>
#include <algorithm>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <numeric>
#include <string>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <list>
#include <bitset>
using namespace std;

#define out(x) cout<< x<< endl
#define ll long long
#define inf 9223372036854775807

struct edge{
  int u, v;
  ll g, s;

  edge() {}
  edge(int a, int b, ll c, ll d) : u(a), v(b), g(c), s(d) {}
};

int n, m, p[205], cnt[205];
vector<edge> graph;

bool lessG(const edge &cmp1, const edge &cmp2){
  return cmp1.g < cmp2.g;
}

bool lessS(const edge &cmp1, const edge &cmp2){
  return cmp1.s < cmp2.s;
}

int find(int x){
  if(p[x] == x) return x;
  return p[x] = find(p[x]);
}

bool link(int &a, int &b){
  if(find(a) != find(b)){
    cnt[find(b)] += cnt[find(a)];
    p[find(a)] = find(b);
    return true;
  }
  return false;
}

ll kruskal(int d){
  for(int i = 1;i <=n;++i){
    p[i] = i;
    cnt[i] = 1;
  }
  ll res;
  sort(graph.begin(), graph.begin() + d, lessS);

  for(int i = 0;i < d; ++i){
    if(link(graph[i].u, graph[i].v)){
      res = graph[i].s;
    }
  }
  if(cnt[find(1)] < n) return -1;
  return res;
}

int main(){
//  freopen("d.in",  "r", stdin);
//  freopen("d.out", "w", stdout);

  ll s, g, res = inf, sil, sv, gt, st;
  int u, v;
  cin>> n>> m>> gt>> st;

  for(int i = 0;i < m; ++i){
    cin>> u>> v>> g>> s;
    graph.push_back(edge(u, v, g * gt, s * st));
  }

  sort(graph.begin(), graph.end(), lessG);
  for(int i = n - 2;i < m; ++i){
    sv = graph[i].g;
    sil = kruskal(i + 1);
    if(sil > -1){
      sil += sv;
      if(sil < res) res = sil;
    }
  }

  if(res < inf) out(res);
  else out(-1);
  return 0;
}


#include <climits>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cctype>
#include <cmath>
#include <algorithm>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <numeric>
#include <string>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <list>
#include <bitset>
using namespace std;

#define ll long long

struct edge{
  int u, v;
  ll g, s;

  bool operator<(const edge &cmp) const{
    return s < cmp.s;
  }
} e[50005], a[50005];

int n, m, cnt, p[205], tam;
ll gt, st;

bool cmpG(edge a, edge b){
  return a.g < b.g;
}

int find(int x){
  if(p[x] == x) return x;
  return p[x] = find(p[x]);
}

bool link(int &a, int &b){
  if(find(a) == find(b)) return false;
  p[find(a)] = find(b);
  return true;
}

ll kruskal(){
  ll res = 0;
  cnt = 0;
  for(int i = 1;i <= n; ++i) p[i] = i;

  sort(a, a + tam);
  for(int i = 0;i < tam; ++i){
    if(link(a[i].u, a[i].v)){
      res = a[i].s;
      a[cnt++] = a[i];
    }
  }
  tam = cnt;
  return res;
}

int main(){
//  freopen("d.in",  "r", stdin);
//  freopen("d.out", "w", stdout);

  scanf("%d%d", &n, &m);
  scanf("%I64d%I64d", &gt, &st);

  ll res = 1ll<<62, sil;
  cnt = tam = 0;

  for(int i = 0;i < m; ++i){
    scanf("%d%d%I64d%I64d", &e[i].u, &e[i].v, &e[i].g, &e[i].s);
    e[i].g *= gt; e[i].s *= st;
  }

  sort(e, e + m, cmpG);
  for(int i = 0;i < m; ++i){
    a[tam++] = e[i];
    sil = kruskal();
    if(cnt == n - 1){
      sil += e[i].g;
      if(sil < res) res = sil;
    }
  }

  if(res < 1ll<<62) printf("%I64d\n", res);
  else printf("-1\n");
  return 0;
}


#include <climits>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cctype>
#include <cmath>
#include <algorithm>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <numeric>
#include <string>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <list>
#include <bitset>
using namespace std;

#define out(x) cout<< x<< endl
#define ll long long

struct edge{
  int u, v;
  ll g, s, w;

  edge() {}
  edge(int a, int b, ll c, ll d, ll e) : u(a), v(b), g(c), s(d), w(e) {}

  bool operator<(const edge &cmp) const{
    if(w == cmp.w){
      if(g == cmp.g){
        if(s == cmp.s){
          if(u == cmp.u) return v < cmp.v;
          return u < cmp.u;
        }
        return s < cmp.s;
      }
      return g < cmp.g;
    }
    return w < cmp.w;
  }
};

int n, m, p[205];
ll gt, st;
vector<edge> graph;

int find(int x){
  if(p[x] == x) return x;
  return p[x] = find(p[x]);
}

bool link(int &a, int &b){
  if(find(a) != find(b)){
    p[find(a)] = find(b);
    return true;
  }
  return false;
}

ll kruskal(){
  ll g = 0, s = 0;
  sort(graph.begin(), graph.end());

  for(int i = 1;i <= n; ++i) p[i] = i;

  for(int i = 0;i < m; ++i){
    if(link(graph[i].u, graph[i].v)){
      if(graph[i].g > g) g = graph[i].g;
      if(graph[i].s > s) s = graph[i].s;
    }
  }

  for(int i = 1;i <= n; ++i){
    for(int j = 1;j < i; ++j){
      if(find(i) != find(j)) return -1;
    }
  }
  return (g * gt + s * st);
}

int main(){
//  freopen("d.in",  "r", stdin);
//  freopen("d.out", "w", stdout);

  ll s, g;
  int u, v;
  cin>> n>> m>> gt>> st;

  for(int i = 0;i < m; ++i){
    cin>> u>> v>> g>> s;
    graph.push_back(edge(u, v, g, s, g * gt + s * st));
  }

  out(kruskal());
  return 0;
}


#include <climits>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cctype>
#include <cmath>
#include <algorithm>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <numeric>
#include <string>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <list>
#include <bitset>
using namespace std;

#define out(x) cout<< x<< endl
#define ll long long
#define inf 9223372036854775807

struct edge{
  int u, v;
  ll g, s;
} graph[50005];

int n, m, p[205], d;

bool lessG(const edge &cmp1, const edge &cmp2){
  return cmp1.g < cmp2.g;
}

bool lessS(const edge &cmp1, const edge &cmp2){
  return cmp1.s < cmp2.s;
}

int find(int x){
  if(p[x] == x) return x;
  return p[x] = find(p[x]);
}

bool link(int &a, int &b){
  if(find(a) != find(b)){
    p[find(a)] = find(b);
    return true;
  }
  return false;
}

ll kruskal(int d){
  for(int i = 1;i <=n;++i) p[i] = i;
  ll res;
  int cnt = 0;
  sort(graph, graph + d, lessS);

  for(int i = 0;i < d; ++i){
    if(link(graph[i].u, graph[i].v)){
      res = graph[i].s;
      ++cnt;
    }
  }

  d = cnt;
  if(cnt < n - 1) return -1;
  return res;
}

int main(){
  freopen("d.in",  "r", stdin);
  freopen("d.out", "w", stdout);

  ll res = inf, sil, sv, gt, st;
  cin>> n>> m>> gt>> st;

  for(int i = 0;i < m; ++i){
    cin>> graph[i].u>> graph[i].v>> graph[i].g>> graph[i].s;
    graph[i].g *= gt;
    graph[i].s *= st;
  }

  d = 0;
  sort(graph, graph + m, lessG);
  for(int i = n - 2;i < m; ++i){
    sv = graph[i].g;
    ++d;
    sil = kruskal(i + 1);
    if(sil > -1){
      sil += sv;
      if(sil < res) res = sil;
    }
  }

  if(res < inf) out(res);
  else out(-1);
  return 0;
}


#include <climits>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cctype>
#include <cmath>
#include <algorithm>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <numeric>
#include <string>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <list>
#include <bitset>
using namespace std;

#define out(x) cout<< x<< endl
#define ll long long
#define inf 9223372036854775807

struct edge{
  int u, v;
  ll g, s;
} graph[50005];

int n, m, p[205], d;

bool lessG(const edge &cmp1, const edge &cmp2){
  return cmp1.g < cmp2.g;
}

bool lessS(const edge &cmp1, const edge &cmp2){
  return cmp1.s < cmp2.s;
}

int find(int x){
  if(p[x] == x) return x;
  return p[x] = find(p[x]);
}

bool link(int &a, int &b){
  if(find(a) != find(b)){
    p[find(a)] = find(b);
    return true;
  }
  return false;
}

ll kruskal(int d){
  for(int i = 1;i <=n;++i) p[i] = i;
  ll res;
  int cnt = 0;
  sort(graph, graph + d, lessS);

  for(int i = 0;i < d; ++i){
    if(link(graph[i].u, graph[i].v)){
      res = graph[i].s;
      ++cnt;
    }
  }

  d = cnt;
  if(cnt < n - 1) return -1;
  return res;
}

int main(){
//  freopen("d.in",  "r", stdin);
//  freopen("d.out", "w", stdout);

  ll res = inf, sil, sv, gt, st;
  scanf("%d%d",&n,&m);
  scanf("%I64d%I64d",&gt,&st);

  for(int i = 0;i < m; ++i){
    scanf("%d%d%I64d%I64d", &graph[i].u, &graph[i].v, &graph[i].g, &graph[i].s);
    graph[i].g *= gt;
    graph[i].s *= st;
  }

  d = 0;
  sort(graph, graph + m, lessG);
  for(int i = n - 2;i < m; ++i){
    sv = graph[i].g;
    ++d;
    sil = kruskal(i + 1);
    if(sil > -1){
      sil += sv;
      if(sil < res) res = sil;
    }
  }

  if(res < inf) out(res);
  else out(-1);
  return 0;
}


#include <climits>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cctype>
#include <cmath>
#include <algorithm>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <numeric>
#include <string>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <list>
#include <bitset>
using namespace std;

#define ll long long

struct edge{
  int u, v;
  ll g, s;

  bool operator<(const edge &cmp) const{
    return g < cmp.g;
  }
} e[50005], a[50005];

int n, m, cnt, p[205], tam;
ll gt, st;

bool cmpS(edge a, edge b){
  return a.s < b.s;
}

int find(int x){
  if(p[x] == x) return x;
  return p[x] = find(p[x]);
}

bool link(int &a, int &b){
  if(find(a) == find(b)) return false;
  p[find(a)] = find(b);
  return true;
}

ll kruskal(){
  ll res = 0;
  cnt = 0;
  for(int i = 1;i <= n; ++i) p[i] = i;

  sort(a, a + tam, cmpS);
  for(int i = 0;i < tam; ++i){
    if(link(a[i].u, a[i].v)){
      res = a[i].s;
      a[cnt++] = a[i];
    }
  }
  tam = cnt;
  return res;
}

int main(){
//  freopen("d.in",  "r", stdin);
//  freopen("d.out", "w", stdout);

  scanf("%d%d", &n, &m);
  scanf("%lld%lld", &gt, &st);

  ll res = 1ll<<62, sil;
  cnt = 0;
  for(int i = 1; i <= n; ++i) p[i] = i;
  for(int i = 0;i < m; ++i){
    scanf("%d%d%I64d%I64d", &e[i].u, &e[i].v, &e[i].g, &e[i].s);
    e[i].g *= gt; e[i].s *= st;
    if(link(e[i].u, e[i].v)) ++cnt;
  }

  if(cnt == n - 1){
    sort(e, e + m);
    for(int i = 0;i < m; ++i){
      a[tam++] = e[i];
      sil = kruskal();
      if(cnt == n - 1){
        sil += e[i].g;
        if(sil < res) res = sil;
      }
    }
    printf("%I64d", res);
  } else {
    printf("-1\n");
  }
  return 0;
}


#include <climits>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cctype>
#include <cmath>
#include <algorithm>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <numeric>
#include <string>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <list>
#include <bitset>
using namespace std;

#define out(x) cout<< x<< endl
#define ll long long
#define inf 9223372036854775807

struct edge{
  int u, v;
  ll g, s;
} graph[50005];

int n, m, p[205], d;

bool lessG(const edge &cmp1, const edge &cmp2){
  return cmp1.g < cmp2.g;
}

bool lessS(const edge &cmp1, const edge &cmp2){
  return cmp1.s < cmp2.s;
}

int find(int x){
  if(p[x] == x) return x;
  return p[x] = find(p[x]);
}

bool link(int &a, int &b){
  if(find(a) != find(b)){
    p[find(a)] = find(b);
    return true;
  }
  return false;
}

ll kruskal(int d){
  for(int i = 1;i <=n;++i) p[i] = i;
  ll res;
  int cnt = 0;
  sort(graph, graph + d, lessS);

  for(int i = 0;i < d; ++i){
    if(link(graph[i].u, graph[i].v)){
      res = graph[i].s;
      ++cnt;
    }
  }

  d = cnt;
  if(cnt < n - 1) return -1;
  return res;
}

int main(){
//  freopen("d.in",  "r", stdin);
//  freopen("d.out", "w", stdout);

  ll res = inf, sil, sv, gt, st;
  cin>> n>> m>> gt>> st;

  for(int i = 0;i < m; ++i){
    cin>> graph[i].u>> graph[i].v>> graph[i].g>> graph[i].s;
    graph[i].g *= gt;
    graph[i].s *= st;
  }

  d = 0;
  sort(graph, graph + m, lessG);
  for(int i = n - 2;i < m; ++i){
    sv = graph[i].g;
    ++d;
    sil = kruskal(i + 1);
    if(sil > -1){
      sil += sv;
      if(sil < res) res = sil;
    }
  }

  if(res < inf) out(res);
  else out(-1);
  return 0;
}


#include <climits>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cctype>
#include <cmath>
#include <algorithm>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <numeric>
#include <string>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <list>
#include <bitset>
using namespace std;

#define out(x) cout<< x<< endl
#define ll long long
#define inf 9223372036854775807

struct edge{
  int u, v;
  ll g, s;
} graph[50005];

int n, m, p[205], d;

bool lessG(const edge &cmp1, const edge &cmp2){
  return cmp1.g < cmp2.g;
}

bool lessS(const edge &cmp1, const edge &cmp2){
  return cmp1.s < cmp2.s;
}

int find(int x){
  if(p[x] == x) return x;
  return p[x] = find(p[x]);
}

bool link(int &a, int &b){
  if(find(a) != find(b)){
    p[find(a)] = find(b);
    return true;
  }
  return false;
}

ll kruskal(){
  for(int i = 1;i <=n;++i) p[i] = i;
  ll res;
  int cnt = 0;
  sort(graph, graph + d, lessS);

  for(int i = 0;i < d; ++i){
    if(link(graph[i].u, graph[i].v)){
      res = graph[i].s;
      ++cnt;
    }
  }

  d = cnt;
  if(cnt < n - 1) return -1;
  return res;
}

int main(){
//  freopen("d.in",  "r", stdin);
//  freopen("d.out", "w", stdout);

  ll res = inf, sil, sv, gt, st;
  scanf("%d%d",&n,&m);
  scanf("%I64d%I64d",&gt,&st);

  for(int i = 0;i < m; ++i){
    scanf("%d%d%I64d%I64d", &graph[i].u, &graph[i].v, &graph[i].g, &graph[i].s);
    graph[i].g *= gt;
    graph[i].s *= st;
  }

  d = n - 2;
  sort(graph, graph + m, lessG);
  for(int i = n - 2;i < m; ++i){
    sv = graph[i].g;
    ++d;
    sil = kruskal();
    if(sil > -1){
      sil += sv;
      if(sil < res) res = sil;
    }
  }

  if(res < inf) out(res);
  else out(-1);
  return 0;
}


#include<vector>
#include<list>
#include<map>
#include<set>
#include<deque>
#include<queue>
#include<stack>
#include<bitset>
#include<algorithm>
#include<functional>
#include<numeric>
#include<utility>
#include<iostream>
#include<sstream>
#include<iomanip>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cctype>
#include<string>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<climits>
#include<complex>
using namespace std;
struct edge
{
    int u,v,g,s;
}a[120000];
bool cmp(const edge&x,const edge&y)
{
    return x.g<y.g;
}
bool cmp1(const edge&x,const edge&y)
{
    return x.s<y.s;
}
struct unionfound
{
    int v[300],n;
    void init(int _n)
    {
        n=_n;
        for (int i=0;i<n;i++)v[i]=i;
    }
    int f(int x)
    {
        return x==v[x]?x:v[x]=f(v[x]);
    }
    int u(int p,int q)
    {
        int x=f(p),y=f(q);
        if (x==y)return 0;
        v[x]=y;
        return 1;
    }
}uf;
int n,m;
long long gg,ss;
int gao(vector<edge>&mst)
{
    sort(mst.begin(),mst.end(),cmp1);
    int i,j,k=0,sz=mst.size();
    uf.init(n+3);
    vector<edge>v;
    int tt=0;
    for (i=0;i<sz;i++)
    {
        if (uf.u(mst[i].u,mst[i].v))
        {
            k++;
            v.push_back(mst[i]);
            tt=max(tt,mst[i].s);
        }
        if (k==n-1)break;
    }
    mst=v;
    return tt;
}
int gao1(vector<edge>&mst)
{
    sort(mst.begin(),mst.end(),cmp);
    int i,j,k=0,sz=mst.size();
    uf.init(n+3);
    vector<edge>v;
    int tt=0;
    for (i=0;i<sz;i++)
    {
        if (uf.u(mst[i].u,mst[i].v))
        {
            k++;
            v.push_back(mst[i]);
            tt=max(tt,mst[i].g);
        }
        if (k==n-1)break;
    }
    mst=v;
    return tt;
}
int main()
{
    int i,j,k;
    scanf("%d%d",&n,&m);
    scanf("%d%d",&i,&j);
    gg=i;
    ss=j;
    for (i=0;i<m;i++)
    {
        scanf("%d%d%d%d",&a[i].u,&a[i].v,&a[i].g,&a[i].s);
    }
    sort(a,a+m,cmp);
    int has=0,tt=0;
    vector<edge>mst;
    uf.init(n+3);
    for (i=0;i<m;i++)
    {
        if (uf.u(a[i].u,a[i].v))
        {
            has++;
            mst.push_back(a[i]);
            tt=max(tt,a[i].s);
        }
        if (has==n-1)break;
    }
    if (i==m&&has<n-1)
    {
        puts("-1");
        return 0;
    }
    long long cst=gg*(long long)a[i].g+ss*(long long)tt;
    for (;i<m;i++)
    {
        mst.push_back(a[i]);
        tt=gao(mst);
        cst=min(cst,gg*(long long)a[i].g+ss*(long long)tt);
    }
    sort(a,a+m,cmp1);
    mst.clear();
    uf.init(n+3);
    has=0;
    tt=0;
    for (i=0;i<m;i++)
    {
        if (uf.u(a[i].u,a[i].v))
        {
            has++;
            mst.push_back(a[i]);
            tt=max(tt,a[i].g);
        }
        if (has==n-1)break;
    }
    cst=min(cst,gg*(long long)tt+ss*(long long)a[i].s);
    for (;i<m;i++)
    {
        mst.push_back(a[i]);
        tt=gao1(mst);
        cst=min(cst,gg*(long long)tt+ss*(long long)a[i].s);
    }
    cout<<cst<<endl;
    return 0;
}


#include<vector>
#include<list>
#include<map>
#include<set>
#include<deque>
#include<queue>
#include<stack>
#include<bitset>
#include<algorithm>
#include<functional>
#include<numeric>
#include<utility>
#include<iostream>
#include<sstream>
#include<iomanip>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cctype>
#include<string>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<climits>
#include<complex>
using namespace std;
struct edge
{
    int u,v,g,s;
}a[120000];
bool cmp(const edge&x,const edge&y)
{
    return x.g<y.g;
}
bool cmp1(const edge&x,const edge&y)
{
    return x.s<y.s;
}
struct unionfound
{
    int v[300],n;
    void init(int _n)
    {
        n=_n;
        for (int i=0;i<n;i++)v[i]=i;
    }
    int f(int x)
    {
        return x==v[x]?x:v[x]=f(v[x]);
    }
    int u(int p,int q)
    {
        int x=f(p),y=f(q);
        if (x==y)return 0;
        v[x]=y;
        return 1;
    }
}uf;
int n,m;
long long gg,ss;
edge mst[120000];
int top;
int gao()
{
    sort(mst,mst+top,cmp1);
    int i,j,k=0,sz=top;
    uf.init(n+3);
    vector<edge>v;
    int tt=0;
    top=0;
    for (i=0;i<sz;i++)
    {
        if (uf.u(mst[i].u,mst[i].v))
        {
            tt=max(tt,mst[i].s);
            mst[k++]=mst[i];
        }
        if (k==n-1)break;
    }
    top=k;
    return tt;
}
int gao1()
{
    sort(mst,mst+top,cmp);
    int i,j,k=0,sz=top;
    uf.init(n+3);
    vector<edge>v;
    int tt=0;
    top=0;
    for (i=0;i<sz;i++)
    {
        if (uf.u(mst[i].u,mst[i].v))
        {
            tt=max(tt,mst[i].g);
            mst[k++]=mst[i];

        }
        if (k==n-1)break;
    }
    top=k;
    return tt;
}
int main()
{
    int i,j,k;
    scanf("%d%d",&n,&m);
    scanf("%d%d",&i,&j);
    gg=i;
    ss=j;
    for (i=0;i<m;i++)
    {
        scanf("%d%d%d%d",&a[i].u,&a[i].v,&a[i].g,&a[i].s);
    }
    sort(a,a+m,cmp);
    int has=0,tt=0;
    top=0;
    vector<edge>cs;
    uf.init(n+3);
    for (i=0;i<m;i++)
    {
        if (uf.u(a[i].u,a[i].v))
        {
            has++;
            mst[top++]=a[i];
            tt=max(tt,a[i].s);
        }
        else
        {
            cs.push_back(a[i]);
        }
        if (has==n-1)break;
    }
    if (i==m&&has<n-1)
    {
        puts("-1");
        return 0;
    }
    int pos=i;
    long long cst=gg*(long long)a[pos].g+ss*(long long)tt;
    for (;i<m;i++)
    {
        cs.push_back(a[i]);
    }
    int sz=cs.size();
    for (i=0;i<sz;i++)
    {
        mst[top++]=cs[i];
        tt=gao();
        cst=min(cst,gg*(long long)max(a[pos].g,cs[i].g)+ss*(long long)tt);
    }
    sort(a,a+m,cmp1);
    top=0;
    cs.clear();
    uf.init(n+3);
    has=0;
    tt=0;
    for (i=0;i<m;i++)
    {
        if (uf.u(a[i].u,a[i].v))
        {
            has++;
            mst[top++]=a[i];
            tt=max(tt,a[i].g);
        }
        else
        {
            cs.push_back(a[i]);
        }
        if (has==n-1)break;
    }
    pos=i;
    cst=min(cst,gg*(long long)tt+ss*(long long)a[pos].s);
    for (;i<m;i++)
    {
        cs.push_back(a[i]);
    }
    sz=cs.size();
    for (i=0;i<sz;i++)
    {
        mst[top++]=a[i];
        tt=gao1();
        cst=min(cst,gg*(long long)tt+ss*(long long)max(a[pos].s,cs[i].s));
    }
    cout<<cst<<endl;
    return 0;
}


#include<vector>
#include<list>
#include<map>
#include<set>
#include<deque>
#include<queue>
#include<stack>
#include<bitset>
#include<algorithm>
#include<functional>
#include<numeric>
#include<utility>
#include<iostream>
#include<sstream>
#include<iomanip>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cctype>
#include<string>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<climits>
#include<complex>
using namespace std;
struct edge
{
	int u,v,g,s;
}a[120000];
bool cmp(const edge&x,const edge&y)
{
	return x.g<y.g;
}
bool cmp1(const edge&x,const edge&y)
{
	return x.s<y.s;
}
struct unionfound
{
	int v[300],n;
	void init(int _n)
	{
		n=_n;
	 	for (int i=0;i<n;i++)v[i]=i;
	}
	int f(int x)
	{
		return x==v[x]?x:v[x]=f(v[x]);
	}
	int u(int p,int q)
	{
		int x=f(p),y=f(q);
		if (x==y)return 0;
		v[x]=y;
		return 1;
	}
}uf;
int n,m;
long long gg,ss;
int gao(vector<edge>&mst)
{
	sort(mst.begin(),mst.end(),cmp1);
	int i,j,k=0,sz=mst.size();
	uf.init(n+3);
	vector<edge>v;
	int tt=0;
	for (i=0;i<sz;i++)
	{
		if (uf.u(mst[i].u,mst[i].v))
		{
			k++;
			v.push_back(mst[i]);
			tt=max(tt,mst[i].s);
		}
		if (k==n-1)break;
	}
	mst=v;
	return tt;
}
int gao1(vector<edge>&mst)
{
	sort(mst.begin(),mst.end(),cmp);
	int i,j,k=0,sz=mst.size();
	uf.init(n+3);
	vector<edge>v;
	int tt=0;
	for (i=0;i<sz;i++)
	{
		if (uf.u(mst[i].u,mst[i].v))
		{
			k++;
			v.push_back(mst[i]);
			tt=max(tt,mst[i].g);
		}
		if (k==n-1)break;
	}
	mst=v;
	return tt;
}
int main()
{
	int i,j,k;
	scanf("%d%d",&n,&m);
	scanf("%d%d",&i,&j);
	gg=i;
	ss=j;
	for (i=0;i<m;i++)
	{
		scanf("%d%d%d%d",&a[i].u,&a[i].v,&a[i].g,&a[i].s);
	}
	sort(a,a+m,cmp);
	int has=0,tt=0;
	vector<edge>mst;
	uf.init(n+3);
	for (i=0;i<m;i++)
	{
		if (uf.u(a[i].u,a[i].v))
		{
			has++;
			mst.push_back(a[i]);
			tt=max(tt,a[i].s);
		}
		if (has==n-1)break;
	}
	if (i==m&&has<n-1)
	{
		puts("-1");
		return 0;
	}
	long long cst=gg*(long long)a[i].g+ss*(long long)tt;
	for (;i<m;i++)
	{
		mst.push_back(a[i]);
		tt=gao(mst);
		cst=min(cst,gg*(long long)a[i].g+ss*(long long)tt);
	}
	sort(a,a+m,cmp1);
	mst.clear();
	uf.init(n+3);
	for (i=0;i<m;i++)
	{
		if (uf.u(a[i].u,a[i].v))
		{
			has++;
			mst.push_back(a[i]);
			tt=max(tt,a[i].g);
		}
		if (has==n-1)break;
	}
	cst=min(cst,gg*(long long)tt+ss*(long long)a[i].s);
	for (;i<m;i++)
	{
		mst.push_back(a[i]);
		tt=gao(mst);
		cst=min(cst,gg*(long long)tt+ss*(long long)a[i].s);
	}
	cout<<cst<<endl;
	return 0;
}


#include<vector>
#include<list>
#include<map>
#include<set>
#include<deque>
#include<queue>
#include<stack>
#include<bitset>
#include<algorithm>
#include<functional>
#include<numeric>
#include<utility>
#include<iostream>
#include<sstream>
#include<iomanip>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cctype>
#include<string>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<climits>
#include<complex>
using namespace std;
struct edge
{
    int u,v,g,s;
}a[120000];
bool cmp(const edge&x,const edge&y)
{
    return x.g<y.g;
}
bool cmp1(const edge&x,const edge&y)
{
    return x.s<y.s;
}
struct unionfound
{
    int v[300],n;
    void init(int _n)
    {
        n=_n;
        for (int i=0;i<n;i++)v[i]=i;
    }
    int f(int x)
    {
        return x==v[x]?x:v[x]=f(v[x]);
    }
    int u(int p,int q)
    {
        int x=f(p),y=f(q);
        if (x==y)return 0;
        v[x]=y;
        return 1;
    }
}uf;
int n,m;
long long gg,ss;
int gao(vector<edge>&mst)
{
    sort(mst.begin(),mst.end(),cmp1);
    int i,j,k=0,sz=mst.size();
    uf.init(n+3);
    vector<edge>v;
    int tt=0;
    for (i=0;i<sz;i++)
    {
        if (uf.u(mst[i].u,mst[i].v))
        {
            k++;
            v.push_back(mst[i]);
            tt=max(tt,mst[i].s);
        }
        if (k==n-1)break;
    }
    mst=v;
    return tt;
}
int gao1(vector<edge>&mst)
{
    sort(mst.begin(),mst.end(),cmp);
    int i,j,k=0,sz=mst.size();
    uf.init(n+3);
    vector<edge>v;
    int tt=0;
    for (i=0;i<sz;i++)
    {
        if (uf.u(mst[i].u,mst[i].v))
        {
            k++;
            v.push_back(mst[i]);
            tt=max(tt,mst[i].g);
        }
        if (k==n-1)break;
    }
    mst=v;
    return tt;
}
int main()
{
    int i,j,k;
    scanf("%d%d",&n,&m);
    scanf("%d%d",&i,&j);
    gg=i;
    ss=j;
    for (i=0;i<m;i++)
    {
        scanf("%d%d%d%d",&a[i].u,&a[i].v,&a[i].g,&a[i].s);
    }
    sort(a,a+m,cmp);
    int has=0,tt=0;
    vector<edge>mst;
    vector<edge>cs;
    uf.init(n+3);
    for (i=0;i<m;i++)
    {
        if (uf.u(a[i].u,a[i].v))
        {
            has++;
            mst.push_back(a[i]);
            tt=max(tt,a[i].s);
        }
        else
        {
            cs.push_back(a[i]);
        }
        if (has==n-1)break;
    }
    if (i==m&&has<n-1)
    {
        puts("-1");
        return 0;
    }
    int pos=i;
    long long cst=gg*(long long)a[pos].g+ss*(long long)tt;
    for (;i<m;i++)
    {
        cs.push_back(a[i]);
    }
    int sz=cs.size();
    for (i=0;i<sz;i++)
    {
        mst.push_back(cs[i]);
        tt=gao(mst);
        cst=min(cst,gg*(long long)max(a[pos].g,cs[i].g)+ss*(long long)tt);
    }
    sort(a,a+m,cmp1);
    mst.clear();
    cs.clear();
    uf.init(n+3);
    has=0;
    tt=0;
    for (i=0;i<m;i++)
    {
        if (uf.u(a[i].u,a[i].v))
        {
            has++;
            mst.push_back(a[i]);
            tt=max(tt,a[i].g);
        }
        else
        {
            cs.push_back(a[i]);
        }
        if (has==n-1)break;
    }
    pos=i;
    cst=min(cst,gg*(long long)tt+ss*(long long)a[pos].s);
    for (;i<m;i++)
    {
        cs.push_back(a[i]);
    }
    sz=cs.size();
    for (i=0;i<sz;i++)
    {
        mst.push_back(cs[i]);
        tt=gao1(mst);
        cst=min(cst,gg*(long long)tt+ss*(long long)max(a[pos].s,cs[i].s));
    }
    cout<<cst<<endl;
    return 0;
}


#include<vector>
#include<list>
#include<map>
#include<set>
#include<deque>
#include<queue>
#include<stack>
#include<bitset>
#include<algorithm>
#include<functional>
#include<numeric>
#include<utility>
#include<iostream>
#include<sstream>
#include<iomanip>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cctype>
#include<string>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<climits>
#include<complex>
using namespace std;
struct edge
{
    int u,v,g,s;
}a[120000];
bool cmp(const edge&x,const edge&y)
{
    return x.g<y.g;
}
bool cmp1(const edge&x,const edge&y)
{
    return x.s<y.s;
}
struct unionfound
{
    int v[300],n;
    void init(int _n)
    {
        n=_n;
        for (int i=0;i<n;i++)v[i]=i;
    }
    int f(int x)
    {
        return x==v[x]?x:v[x]=f(v[x]);
    }
    int u(int p,int q)
    {
        int x=f(p),y=f(q);
        if (x==y)return 0;
        v[x]=y;
        return 1;
    }
}uf;
int n,m;
long long gg,ss;
int gao(vector<edge>&mst)
{
    sort(mst.begin(),mst.end(),cmp1);
    int i,j,k=0,sz=mst.size();
    uf.init(n+3);
    vector<edge>v;
    int tt=0;
    for (i=0;i<sz;i++)
    {
        if (uf.u(mst[i].u,mst[i].v))
        {
            k++;
            v.push_back(mst[i]);
            tt=max(tt,mst[i].s);
        }
        if (k==n-1)break;
    }
    mst=v;
    return tt;
}
int gao1(vector<edge>&mst)
{
    sort(mst.begin(),mst.end(),cmp);
    int i,j,k=0,sz=mst.size();
    uf.init(n+3);
    vector<edge>v;
    int tt=0;
    for (i=0;i<sz;i++)
    {
        if (uf.u(mst[i].u,mst[i].v))
        {
            k++;
            v.push_back(mst[i]);
            tt=max(tt,mst[i].g);
        }
        if (k==n-1)break;
    }
    mst=v;
    return tt;
}
int main()
{
    int i,j,k;
    scanf("%d%d",&n,&m);
    scanf("%d%d",&i,&j);
    gg=i;
    ss=j;
    for (i=0;i<m;i++)
    {
        scanf("%d%d%d%d",&a[i].u,&a[i].v,&a[i].g,&a[i].s);
    }
    sort(a,a+m,cmp);
    int has=0,tt=0;
    vector<edge>mst;
    vector<edge>cs;
    uf.init(n+3);
    for (i=0;i<m;i++)
    {
        if (uf.u(a[i].u,a[i].v))
        {
            has++;
            mst.push_back(a[i]);
            tt=max(tt,a[i].s);
        }
        else
        {
            cs.push_back(a[i]);
        }
        if (has==n-1)break;
    }
    if (i==m&&has<n-1)
    {
        puts("-1");
        return 0;
    }
    long long cst=gg*(long long)a[i].g+ss*(long long)tt;
    for (;i<m;i++)
    {
        cs.push_back(a[i]);
    }
    int sz=cs.size();
    for (i=0;i<sz;i++)
    {
        mst.push_back(cs[i]);
        tt=gao(mst);
        cst=min(cst,gg*(long long)cs[i].g+ss*(long long)tt);
    }
    sort(a,a+m,cmp1);
    mst.clear();
    cs.clear();
    uf.init(n+3);
    has=0;
    tt=0;
    for (i=0;i<m;i++)
    {
        if (uf.u(a[i].u,a[i].v))
        {
            has++;
            mst.push_back(a[i]);
            tt=max(tt,a[i].g);
        }
        else
        {
            cs.push_back(a[i]);
        }
        if (has==n-1)break;
    }
    cst=min(cst,gg*(long long)tt+ss*(long long)a[i].s);
    for (;i<m;i++)
    {
        cs.push_back(a[i]);
    }
    sz=cs.size();
    for (i=0;i<sz;i++)
    {
        mst.push_back(cs[i]);
        tt=gao1(mst);
        cst=min(cst,gg*(long long)tt+ss*(long long)cs[i].s);
    }
    cout<<cst<<endl;
    return 0;
}