#include <bits/stdc++.h>
using namespace std;
#define bye ios_base::sync_with_stdio(false), cin.tie(NULL), cout.tie(NULL);
#define ll long long
#define pb push_back
#define pf push_front
#define mp make_pair
#define fr first.first
#define th second.first
#define sc first.second
#define fo second.second
#define MOD (ll)(998244353)

ll n,m,G,S,p[200200];
vector<pair<pair<ll,ll>,ll > >g[200200];
vector<pair<pair<ll,ll>,pair<ll,ll> > >ed,tkn;
vector<pair<ll,pair<ll,ll> > >cy,tem;
ll ans = 1e18;
bool flag = 0;
bool vis[220];

ll findp(ll u)
{
    if(p[u]==u)
        return u;
    return p[u] = findp(p[u]);
}

void dfs(ll u,ll p)
{
    if(vis[u])
        return;
    vis[u] = 1;
    for(int i=0; i<g[u].size(); i++)
    {
        if(vis[g[u][i].second]&&g[u][i].second!=p)
        {
            cy = tem;
            cy.pb({g[u][i].sc,{u,g[u][i].second}});
        }
        tem.pb({g[u][i].sc,{u,g[u][i].second}});
        dfs(g[u][i].second,u);
        tem.pop_back();
    }
}

int main()
{
    bye

    cin >> n >> m >> G >> S;

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

    for(int i=0; i<m; i++)
    {
        ll x,y,z,u;
        cin >> x >> y >> z >> u;

        ed.pb({{z,u},{x,y}});

    }

    sort(ed.begin(),ed.end());

    multiset<ll>mxs;

    int i=0;
    for(int i=0; i<m; i++)
    {

        if(ed[i].th==ed[i].fo)
            continue;

        mxs.insert(ed[i].sc);

        g[ed[i].th].pb({{ed[i].fr,ed[i].sc},ed[i].fo});
        g[ed[i].fo].pb({{ed[i].fr,ed[i].sc},ed[i].th});

        ll x = findp(ed[i].th);
        ll y = findp(ed[i].fo);

        if(x!=y)
        {
            p[x] = y;
        }

        tkn.pb(ed[i]);

        break;
    }

    for(++i; i<m; i++)
    {
        if(ed[i].th==ed[i].fo)
            continue;
        for(int j=1;j<=n;j++)
            vis[j] = 0;
        ll x = ed[i].th,y = ed[i].fo;
        //cout << x << " " << y << " dgdgfdsf" << endl;
        x = findp(x);
        y = findp(y);
        g[ed[i].th].pb({{ed[i].fr,ed[i].sc},ed[i].fo});
        g[ed[i].fo].pb({{ed[i].fr,ed[i].sc},ed[i].th});
        if(x!=y)
        {
            tkn.pb(ed[i]);
            p[x] = y;
            mxs.insert(ed[i].sc);
        }
        else
        {
           // cout << "          123 " << endl;
            int idx = -1;
            for(int j=0; j<tkn.size(); j++)
            {
                if(max(ed[i].th,ed[i].fo)==max(tkn[j].th,tkn[j].fo)
                        && min(ed[i].th,ed[i].fo)==min(tkn[j].th,tkn[j].fo))
                {
                    if(ed[i].sc<tkn[j].sc)
                    {
                        idx = j;
                        break;
                    }
                }
            }
            if(idx!=-1)
            {
                ll x1 = tkn[idx].th;
                ll y1 = tkn[idx].fo;
                int id = -1;
                for(int j=0; j<g[x1].size(); j++)
                {
                    if(g[x1][j].second==y1)
                        id = j;
                }
                if(id!=-1)
                    g[x1].erase(g[x1].begin()+id);

                id = -1;
                for(int j=0; j<g[y1].size(); j++)
                {
                    if(g[y1][j].second==x1)
                        id = j;
                }
                if(id!=-1)
                    g[y1].erase(g[y1].begin()+id);
                mxs.erase(mxs.find(tkn[idx].sc));
                tkn.erase(tkn.begin()+idx);
                continue;
            }

            cy.clear();
            tem.clear();

            dfs(x,0);

            sort(cy.begin(),cy.end());

            int sz = cy.size();
            sz--;
            ll x1 = cy[sz].th;
            ll y1 = cy[sz].fo;

           // cout << 1 << endl;
            int id = -1;
            for(int j=0; j<g[x1].size(); j++)
            {
                if(g[x1][j].second==y1)
                    id = j;
            }
            if(id!=-1)
                g[x1].erase(g[x1].begin()+id);

            id = -1;
            for(int j=0; j<g[y1].size(); j++)
            {
                if(g[y1][j].second==x1)
                    id = j;
            }
            if(id!=-1)
                g[y1].erase(g[y1].begin()+id);

            mxs.erase(mxs.find(cy[cy.size()-1].first));

            idx=0;

            for(idx;idx<tkn.size();idx++)
                if(max(tkn[idx].th,tkn[idx].fo) == max(x1,y1)
                   &&min(tkn[idx].th,tkn[idx].fo) == min(x1,y1))
                    break;
            if(idx!=tkn.size())
                tkn.erase(tkn.begin()+idx);
        }
        set<ll>cnt;
        for(int j=1;j<=n;j++)
            cnt.insert(findp(j));
        if(cnt.size()==1){
            ll sum = ed[i].fr*G;
            multiset<ll>::iterator it = mxs.end();
            it--;
            sum += ((*it)*S);
            ans = min(ans,sum);
            flag = 1;
        }
    }

    if(flag)
    cout << ans << "\n";
    else
        cout << -1;
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define bye ios_base::sync_with_stdio(false), cin.tie(NULL), cout.tie(NULL);
#define ll long long
#define pb push_back
#define pf push_front
#define mp make_pair
#define fr first.first
#define th second.first
#define sc first.second
#define fo second.second
#define MOD (ll)(998244353)

ll n,m,G,S,p[200200];
vector<pair<pair<ll,ll>,ll > >g[200200];
vector<pair<pair<ll,ll>,pair<ll,ll> > >ed,tkn;
vector<pair<ll,pair<ll,ll> > >cy,tem;
ll ans = 1e18;
bool flag = 0;
bool vis[220];

ll findp(ll u)
{
    if(p[u]==u)
        return u;
    return p[u] = findp(p[u]);
}

void dfs(ll u,ll p)
{
    if(vis[u])
        return;
    vis[u] = 1;
    for(int i=0; i<g[u].size(); i++)
    {
        if(vis[g[u][i].second]&&g[u][i].second!=p)
        {
            cy = tem;
            cy.pb({g[u][i].sc,{u,g[u][i].second}});
        }
        tem.pb({g[u][i].sc,{u,g[u][i].second}});
        dfs(g[u][i].second,u);
        tem.pop_back();
    }
}

int main()
{
    bye

    cin >> n >> m >> G >> S;

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

    for(int i=0; i<m; i++)
    {
        ll x,y,z,u;
        cin >> x >> y >> z >> u;

        ed.pb({{z,u},{x,y}});

    }

    sort(ed.begin(),ed.end());

    multiset<ll>mxs;

    int i=0;

    for(i; i<m; i++)
    {
        if(ed[i].th==ed[i].fo)
            continue;

        for(int j=1; j<=n; j++)
            vis[j] = 0;

        ll x = ed[i].th,y = ed[i].fo;

        x = findp(x);
        y = findp(y);

        if(x!=y)
        {
            tkn.pb(ed[i]);
            p[x] = y;
            mxs.insert(ed[i].sc);
        }

        else
        {
            int idx = -1;
            bool f=0;
            for(int j=0; j<tkn.size(); j++)
            {
                if(max(ed[i].th,ed[i].fo)==max(tkn[j].th,tkn[j].fo)
                        && min(ed[i].th,ed[i].fo)==min(tkn[j].th,tkn[j].fo))
                {
                    if(ed[i].sc<tkn[j].sc)
                    {
                        idx = j;
                        break;
                    }
                    f = 1;
                }
            }
            if(idx!=-1)
            {
                ll x1 = tkn[idx].th;
                ll y1 = tkn[idx].fo;
                int id = -1;

                mxs.erase(mxs.find(tkn[idx].sc));

                tkn.erase(tkn.begin()+idx);

                mxs.insert(ed[i].sc);

                tkn.pb(ed[i]);

                continue;
            }

            if(f)
                continue;

            for(int i=1;i<=n;i++){
                g[i].clear();
            }

            tkn.pb(ed[i]);

            for(int j=0;j<tkn.size();j++){
                g[tkn[j].th].pb({{tkn[j].fr,tkn[j].sc},tkn[j].fo});
                g[tkn[j].fo].pb({{tkn[j].fr,tkn[j].sc},tkn[j].th});
            }

            mxs.insert(ed[i].sc);

            cy.clear();
            tem.clear();

            dfs(x,0);

            sort(cy.begin(),cy.end());

            if(cy.size()){
            int sz = cy.size();
            sz--;
            ll x1 = cy[sz].th;
            ll y1 = cy[sz].fo;

            int id = -1;

            mxs.erase(mxs.find(cy[sz].first));

            idx=0;

            for(idx; idx<tkn.size(); idx++)
                if(max(tkn[idx].th,tkn[idx].fo) == max(x1,y1)
                        &&min(tkn[idx].th,tkn[idx].fo) == min(x1,y1))
                            break;

            if(idx!=tkn.size())
                tkn.erase(tkn.begin()+idx);
        }
        }

        set<ll>cnt;
        for(int j=1; j<=n; j++)
            cnt.insert(findp(j));

        if(cnt.size()==1)
        {
            ll sum = ed[i].fr*G;
            multiset<ll>::iterator it = mxs.end();
            it--;
            ll smu = *it;
            smu*=S;
            sum += smu;
            ans = min(ans,sum);
            flag = 1;
        }
    }

    if(flag)
        cout << ans << "\n";
    else
        cout << -1;
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define bye ios_base::sync_with_stdio(false), cin.tie(NULL), cout.tie(NULL);
#define ll long long
#define pb push_back
#define pf push_front
#define mp make_pair
#define fr first.first
#define th second.first
#define sc first.second
#define fo second.second
#define MOD (ll)(998244353)

ll n,m,G,S,p[200200];
vector<pair<pair<ll,ll>,ll > >g[200200];
vector<pair<pair<ll,ll>,pair<ll,ll> > >ed,tkn;
vector<pair<ll,pair<ll,ll> > >cy,tem;
ll ans = 1e18;
bool flag = 0;
bool vis[220];

ll findp(ll u)
{
    if(p[u]==u)
        return u;
    return p[u] = findp(p[u]);
}

void dfs(ll u,ll p,ll st)
{
    if(vis[u])
        return;
    vis[u] = 1;
//    cout << u << endl;
    for(int i=0; i<g[u].size(); i++)
    {
        if(vis[g[u][i].second]&&g[u][i].second!=p&&g[u][i].second==st)
        {
            cy = tem;
            cy.pb({g[u][i].sc,{u,g[u][i].second}});
            return;
        }
        if(!vis[g[u][i].second])
        {
            tem.pb({g[u][i].sc,{u,g[u][i].second}});
            dfs(g[u][i].second,u,st);
            tem.pop_back();
        }
    }
}

int main()
{
    bye

    cin >> n >> m >> G >> S;

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

    for(int i=0; i<m; i++)
    {
        ll x,y,z,u;
        cin >> x >> y >> z >> u;

        ed.pb({{z,u},{x,y}});

    }

    sort(ed.begin(),ed.end());

    multiset<ll>mxs;

    int i=0;

    for(i; i<m; i++)
    {
        if(ed[i].th==ed[i].fo)
            continue;

        for(int j=0; j<=n; j++)
            vis[j] = 0;

        ll x = ed[i].th,y = ed[i].fo;

        x = findp(x);
        y = findp(y);

        if(x!=y)
        {
            tkn.pb(ed[i]);
            p[x] = y;
            mxs.insert(ed[i].sc);
        }

        else
        {
            int idx = -1;
            bool f=0;
            for(int j=0; j<tkn.size(); j++)
            {
                if(max(ed[i].th,ed[i].fo)==max(tkn[j].th,tkn[j].fo)
                        && min(ed[i].th,ed[i].fo)==min(tkn[j].th,tkn[j].fo))
                {
                    if(ed[i].sc<tkn[j].sc)
                    {
                        idx = j;
                        break;
                    }
                    f = 1;
                }
            }
            if(idx!=-1)
            {
                ll x1 = tkn[idx].th;
                ll y1 = tkn[idx].fo;

                mxs.erase(mxs.find(tkn[idx].sc));

                tkn.erase(tkn.begin()+idx);

                mxs.insert(ed[i].sc);

                tkn.pb(ed[i]);

            }
            else{
            if(f)
                continue;

            for(int i=1; i<=n; i++)
            {
                g[i].clear();
            }

            tkn.pb(ed[i]);

            for(int j=0; j<tkn.size(); j++)
            {
                g[tkn[j].th].pb({{tkn[j].fr,tkn[j].sc},tkn[j].fo});
                g[tkn[j].fo].pb({{tkn[j].fr,tkn[j].sc},tkn[j].th});
            }

            mxs.insert(ed[i].sc);

            cy.clear();
            tem.clear();

            dfs(ed[i].th,0,ed[i].th);

            sort(cy.begin(),cy.end());

            if(cy.size())
            {

                int sz = cy.size();
                sz--;
                ll x1 = cy[sz].th;
                ll y1 = cy[sz].fo;

//                for(int j=0; j<cy.size(); j++)
//                    cout << cy[j].th << " " << cy[j].fo << "______ " << cy[j].first << "\n";
                int id = -1;

                mxs.erase(mxs.find(cy[sz].first));

                idx=0;

                for(idx; idx<tkn.size(); idx++)
                    if(max(tkn[idx].th,tkn[idx].fo) == max(x1,y1)
                            &&min(tkn[idx].th,tkn[idx].fo) == min(x1,y1))
                        break;

                if(idx!=tkn.size())
                    tkn.erase(tkn.begin()+idx);
            }
        }
        }
        set<ll>cnt;
        for(int j=1; j<=n; j++)
            cnt.insert(findp(j));

        if(cnt.size()==1)
        {
            ll sum = ed[i].fr*G;
            multiset<ll>::iterator it = mxs.end();
            it--;
            ll smu = *it;
            smu*=S;
            sum += smu;
            ans = min(ans,sum);
            flag = 1;
        }
    }

    if(flag)
        cout << ans << "\n";
    else
        cout << -1;
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define bye ios_base::sync_with_stdio(false), cin.tie(NULL), cout.tie(NULL);
#define ll long long
#define pb push_back
#define pf push_front
#define mp make_pair
#define fr first.first
#define th second.first
#define sc first.second
#define fo second.second
#define MOD (ll)(998244353)

ll n,m,G,S,p[200200];
vector<pair<pair<ll,ll>,ll > >g[200200];
vector<pair<pair<ll,ll>,pair<ll,ll> > >ed,tkn;
vector<pair<ll,pair<ll,ll> > >cy,tem;
ll ans = 1e18;
bool flag = 0;
bool vis[220];

ll findp(ll u)
{
    if(p[u]==u)
        return u;
    return p[u] = findp(p[u]);
}

void dfs(ll u,ll p)
{
    if(vis[u])
        return;
    vis[u] = 1;
    for(int i=0; i<g[u].size(); i++)
    {
        if(vis[g[u][i].second]&&g[u][i].second!=p)
        {
            cy = tem;
            cy.pb({g[u][i].sc,{u,g[u][i].second}});
        }
        tem.pb({g[u][i].sc,{u,g[u][i].second}});
        dfs(g[u][i].second,u);
        tem.pop_back();
    }
}

int main()
{
    bye

    cin >> n >> m >> G >> S;

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

    for(int i=0; i<m; i++)
    {
        ll x,y,z,u;
        cin >> x >> y >> z >> u;

        ed.pb({{z,u},{x,y}});

    }

    sort(ed.begin(),ed.end());

    multiset<ll>mxs;

    int i=0;

    for(i; i<m; i++)
    {
        if(ed[i].th==ed[i].fo)
            continue;

        for(int j=1; j<=n; j++)
            vis[j] = 0;

        ll x = ed[i].th,y = ed[i].fo;

        x = findp(x);
        y = findp(y);

        if(x!=y)
        {
            tkn.pb(ed[i]);
            p[x] = y;
            mxs.insert(ed[i].sc);
        }

        else
        {
            int idx = -1;
            bool f=0;
            for(int j=0; j<tkn.size(); j++)
            {
                if(max(ed[i].th,ed[i].fo)==max(tkn[j].th,tkn[j].fo)
                        && min(ed[i].th,ed[i].fo)==min(tkn[j].th,tkn[j].fo))
                {
                    if(ed[i].sc<tkn[j].sc)
                    {
                        idx = j;
                        break;
                    }
                    f = 1;
                }
            }
            if(idx!=-1)
            {
                ll x1 = tkn[idx].th;
                ll y1 = tkn[idx].fo;
                int id = -1;

                mxs.erase(mxs.find(tkn[idx].sc));

                tkn.erase(tkn.begin()+idx);

                mxs.insert(ed[i].sc);

                tkn.pb(ed[i]);

                continue;
            }

            if(f)
                continue;

            for(int i=1;i<=n;i++){
                g[i].clear();
            }

            tkn.pb(ed[i]);

            for(int j=0;j<tkn.size();j++){
                g[tkn[j].th].pb({{tkn[j].fr,tkn[j].sc},tkn[j].fo});
                g[tkn[j].fo].pb({{tkn[j].fr,tkn[j].sc},tkn[j].th});
            }

            mxs.insert(ed[i].sc);

            cy.clear();
            tem.clear();

            dfs(x,0);

            sort(cy.begin(),cy.end());

            int sz = cy.size();
            sz--;
            ll x1 = cy[sz].th;
            ll y1 = cy[sz].fo;

            int id = -1;

            mxs.erase(mxs.find(cy[sz].first));

            idx=0;

            for(idx; idx<tkn.size(); idx++)
                if(max(tkn[idx].th,tkn[idx].fo) == max(x1,y1)
                        &&min(tkn[idx].th,tkn[idx].fo) == min(x1,y1))
                            break;

            if(idx!=tkn.size())
                tkn.erase(tkn.begin()+idx);
        }

        set<ll>cnt;
        for(int j=1; j<=n; j++)
            cnt.insert(findp(j));

        if(cnt.size()==1)
        {
            ll sum = ed[i].fr*G;
            multiset<ll>::iterator it = mxs.end();
            it--;
            ll smu = *it;
            smu*=S;
            sum += smu;
            ans = min(ans,sum);
            flag = 1;
        }
    }

    if(flag)
        cout << ans << "\n";
    else
        cout << -1;
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define bye ios_base::sync_with_stdio(false), cin.tie(NULL), cout.tie(NULL);
#define ll long long
#define pb push_back
#define pf push_front
#define mp make_pair
#define fr first.first
#define th second.first
#define sc first.second
#define fo second.second
#define MOD (ll)(998244353)

ll n,m,G,S,p[200200];
vector<pair<pair<ll,ll>,ll > >g[200200];
vector<pair<pair<ll,ll>,pair<ll,ll> > >ed,tkn;
vector<pair<ll,pair<ll,ll> > >cy,tem;
ll ans = 1e18;
bool flag = 0;
bool vis[220];

ll findp(ll u)
{
    if(p[u]==u)
        return u;
    return p[u] = findp(p[u]);
}

void dfs(ll u,ll p)
{
    if(vis[u])
        return;
    vis[u] = 1;
    for(int i=0; i<g[u].size(); i++)
    {
        if(vis[g[u][i].second]&&g[u][i].second!=p)
        {
            cy = tem;
            cy.pb({g[u][i].sc,{u,g[u][i].second}});
        }
        tem.pb({g[u][i].sc,{u,g[u][i].second}});
        dfs(g[u][i].second,u);
        tem.pop_back();
    }
}

int main()
{
    bye

    cin >> n >> m >> G >> S;

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

    for(int i=0; i<m; i++)
    {
        ll x,y,z,u;
        cin >> x >> y >> z >> u;

        ed.pb({{z,u},{x,y}});

    }

    sort(ed.begin(),ed.end());

    multiset<ll>mxs;

    int i=0;
    for(int i=0; i<m; i++)
    {
        for(int i=1;i<=n;i++)
            vis[i] = 0;

        if(ed[i].th==ed[i].fo)
            continue;

        mxs.insert(ed[i].sc);

        g[ed[i].th].pb({{ed[i].fr,ed[i].sc},ed[i].fo});
        g[ed[i].fo].pb({{ed[i].fr,ed[i].sc},ed[i].th});

        ll x = findp(ed[i].th);
        ll y = findp(ed[i].fo);

        if(x!=y)
        {
            p[x] = y;
        }

        tkn.pb(ed[i]);

        break;
    }

    for(++i; i<m; i++)
    {
        ll x = ed[i].th,y = ed[i].fo;
        //cout << x << " " << y << " dgdgfdsf" << endl;
        x = findp(x);
        y = findp(y);
        g[ed[i].th].pb({{ed[i].fr,ed[i].sc},ed[i].fo});
        g[ed[i].fo].pb({{ed[i].fr,ed[i].sc},ed[i].th});
        if(x!=y)
        {
            tkn.pb(ed[i]);
            p[x] = y;
            mxs.insert(ed[i].sc);
        }
        else
        {
           // cout << "          123 " << endl;
            int idx = -1;
            for(int j=0; j<tkn.size(); j++)
            {
                if(max(ed[i].th,ed[i].fo)==max(tkn[j].th,tkn[j].fo)
                        && min(ed[i].th,ed[i].fo)==min(tkn[j].th,tkn[j].fo))
                {
                    if(ed[i].sc<tkn[j].sc)
                    {
                        idx = j;
                        break;
                    }
                }
            }
            if(idx!=-1)
            {
                ll x1 = tkn[idx].th;
                ll y1 = tkn[idx].fo;
                int id = -1;
                for(int j=0; j<g[x1].size(); j++)
                {
                    if(g[x1][j].second==y1)
                        id = j;
                }
                if(id!=-1)
                    g[x1].erase(g[x1].begin()+id);

                id = -1;
                for(int j=0; j<g[y1].size(); j++)
                {
                    if(g[y1][j].second==x1)
                        id = j;
                }
                if(id!=-1)
                    g[y1].erase(g[y1].begin()+id);
                mxs.erase(mxs.find(tkn[idx].sc));
                tkn.erase(tkn.begin()+idx);
                continue;
            }

            cy.clear();
            tem.clear();

            dfs(x,0);

            sort(cy.begin(),cy.end());

            int sz = cy.size();
            sz--;
            ll x1 = cy[sz].th;
            ll y1 = cy[sz].fo;

           // cout << 1 << endl;
            int id = -1;
            for(int j=0; j<g[x1].size(); j++)
            {
                if(g[x1][j].second==y1)
                    id = j;
            }
            if(id!=-1)
                g[x1].erase(g[x1].begin()+id);

            id = -1;
            for(int j=0; j<g[y1].size(); j++)
            {
                if(g[y1][j].second==x1)
                    id = j;
            }
            if(id!=-1)
                g[y1].erase(g[y1].begin()+id);

            mxs.erase(mxs.find(cy[cy.size()-1].first));

            idx=0;

            for(idx;idx<tkn.size();idx++)
                if(max(tkn[idx].th,tkn[idx].fo) == max(x1,y1)
                   &&min(tkn[idx].th,tkn[idx].fo) == min(x1,y1))
                    break;
            if(idx!=tkn.size())
                tkn.erase(tkn.begin()+idx);
        }
        set<ll>cnt;
        for(int j=1;j<=n;j++)
            cnt.insert(findp(j));
        if(cnt.size()==1){
            ll sum = ed[i].fr*G;
            multiset<ll>::iterator it = mxs.end();
            it--;
            sum += ((*it)*S);
            ans = min(ans,sum);
            flag = 1;
        }
    }

    if(flag)
    cout << ans << "\n";
    else
        cout << -1;
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define bye ios_base::sync_with_stdio(false), cin.tie(NULL), cout.tie(NULL);
#define ll long long
#define pb push_back
#define pf push_front
#define mp make_pair
#define fr first.first
#define th second.first
#define sc first.second
#define fo second.second
#define MOD (ll)(998244353)

ll n,m,G,S,p[200200];
vector<pair<pair<ll,ll>,ll > >g[200200];
vector<pair<pair<ll,ll>,pair<ll,ll> > >ed,tkn;
vector<pair<ll,pair<ll,ll> > >cy,tem;
ll ans = 1e18;
bool flag = 0;
bool vis[220];

ll findp(ll u)
{
    if(p[u]==u)
        return u;
    return p[u] = findp(p[u]);
}

void dfs(ll u,ll p)
{
    if(vis[u])
        return;
    vis[u] = 1;
    for(int i=0; i<g[u].size(); i++)
    {
        if(vis[g[u][i].second]&&g[u][i].second!=p)
        {
            cy = tem;
            cy.pb({g[u][i].sc,{u,g[u][i].second}});
        }
        tem.pb({g[u][i].sc,{u,g[u][i].second}});
        dfs(g[u][i].second,u);
        tem.pop_back();
    }
}

int main()
{
    bye

    cin >> n >> m >> G >> S;

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

    for(int i=0; i<m; i++)
    {
        ll x,y,z,u;
        cin >> x >> y >> z >> u;

        ed.pb({{z,u},{x,y}});

    }

    sort(ed.begin(),ed.end());

    multiset<ll>mxs;

    int i=0;
    for(int i=0; i<m; i++)
    {

        if(ed[i].th==ed[i].fo)
            continue;

        mxs.insert(ed[i].sc);

        g[ed[i].th].pb({{ed[i].fr,ed[i].sc},ed[i].fo});
        g[ed[i].fo].pb({{ed[i].fr,ed[i].sc},ed[i].th});

        ll x = findp(ed[i].th);
        ll y = findp(ed[i].fo);

        if(x!=y)
        {
            p[x] = y;
        }

        tkn.pb(ed[i]);

        break;
    }

    for(++i; i<m; i++)
    {
        if(ed[i].th==ed[i].fo)
            continue;
        for(int j=1; j<=n; j++)
            vis[j] = 0;
        ll x = ed[i].th,y = ed[i].fo;
        //cout << x << " " << y << " dgdgfdsf" << endl;
        x = findp(x);
        y = findp(y);

        mxs.insert(ed[i].sc);

        if(x!=y)
        {
            g[ed[i].th].pb({{ed[i].fr,ed[i].sc},ed[i].fo});
            g[ed[i].fo].pb({{ed[i].fr,ed[i].sc},ed[i].th});
            tkn.pb(ed[i]);
            p[x] = y;
        }

        else
        {
            // cout << "          123 " << endl;
            int idx = -1;
            for(int j=0; j<tkn.size(); j++)
            {
                if(max(ed[i].th,ed[i].fo)==max(tkn[j].th,tkn[j].fo)
                        && min(ed[i].th,ed[i].fo)==min(tkn[j].th,tkn[j].fo))
                {
                    if(ed[i].sc<tkn[j].sc)
                    {
                        idx = j;
                        break;
                    }
                }
            }
            if(idx!=-1)
            {
                ll x1 = tkn[idx].th;
                ll y1 = tkn[idx].fo;
                int id = -1;
                for(int j=0; j<g[x1].size(); j++)
                {
                    if(g[x1][j].second==y1)
                        id = j;
                }
                if(id!=-1)
                    g[x1].erase(g[x1].begin()+id);

                id = -1;
                for(int j=0; j<g[y1].size(); j++)
                {
                    if(g[y1][j].second==x1)
                        id = j;
                }
                if(id!=-1)
                    g[y1].erase(g[y1].begin()+id);
                mxs.erase(mxs.find(tkn[idx].sc));
                tkn.erase(tkn.begin()+idx);
                g[ed[i].th].pb({{ed[i].fr,ed[i].sc},ed[i].fo});
                g[ed[i].fo].pb({{ed[i].fr,ed[i].sc},ed[i].th});
                continue;
            }

            g[ed[i].th].pb({{ed[i].fr,ed[i].sc},ed[i].fo});
            g[ed[i].fo].pb({{ed[i].fr,ed[i].sc},ed[i].th});

            cy.clear();
            tem.clear();

            dfs(x,0);

            sort(cy.begin(),cy.end());

            int sz = cy.size();
            sz--;
            ll x1 = cy[sz].th;
            ll y1 = cy[sz].fo;

            // cout << 1 << endl;
            int id = -1;
            for(int j=0; j<g[x1].size(); j++)
            {
                if(g[x1][j].second==y1)
                    id = j;
            }
            if(id!=-1)
                g[x1].erase(g[x1].begin()+id);

            id = -1;
            for(int j=0; j<g[y1].size(); j++)
            {
                if(g[y1][j].second==x1)
                    id = j;
            }
            if(id!=-1)
                g[y1].erase(g[y1].begin()+id);

            mxs.erase(mxs.find(cy[cy.size()-1].first));

            idx=0;

            for(idx; idx<tkn.size(); idx++)
                if(max(tkn[idx].th,tkn[idx].fo) == max(x1,y1)
                        &&min(tkn[idx].th,tkn[idx].fo) == min(x1,y1))
                    break;
            if(idx!=tkn.size())
                tkn.erase(tkn.begin()+idx);
        }
        set<ll>cnt;
        for(int j=1; j<=n; j++)
            cnt.insert(findp(j));
        if(cnt.size()==1)
        {
            ll sum = ed[i].fr*G;
            multiset<ll>::iterator it = mxs.end();
            it--;
            ll smu = *it;
            smu*=S;
            sum += smu;
            ans = min(ans,sum);
            flag = 1;
        }
    }

    if(flag)
        cout << ans << "\n";
    else
        cout << -1;
    return 0;
}


#include <iostream>
#include <bits/stdc++.h>
#define ll long long

using namespace std;
const int N = 50010;
int G,S,n,m,Hash = 1,Gold[N];
const ll Inf = 9e18;

struct Edge
{
    int u,v,g,s;
} edges[50100];

bool cmp(const struct Edge &s1, const struct Edge &s2)
{
    return s1.s < s2.s;
}

struct Node
{
    int par[201],Size[201];
    int comp;
    inline void init()
    {
        for(ll i=1; i<=n; i++)  Size[i]=1,par[i]=i;
        comp = n;
    }
    inline int getparent(int x)
    {
        if(x==par[x])  return x;
        return par[x]=getparent(par[x]);
    }
    inline void Merge(int x , int y)
    {
        x = getparent(x);
        y = getparent(y);
        if(x==y)  return ;
        if(Size[x] < Size[y])  swap(x,y);
        Size[x]+=Size[y];
        par[y] = x;
        comp--;
    }
    inline struct Node operator +(struct Node &s)
    {
        Node temp = *this;
        for(ll i = 1; i<=n; i++)  temp.Merge(getparent(i) , s.getparent(i));
        return temp;
    }
}Seg[N * 3];

unordered_map < int , int > mp;
vector < int > v;

void Build(int p = 1, int L = 1, int R = N)
{
    if (L == R)
    {
        Seg[p].init();
        return;
    }
    int mid = (L + R)/2;
    Build(p * 2, L, mid);
    Build(p * 2 + 1, mid + 1, R);

    Seg[p] = Seg[p * 2] + Seg[p * 2 + 1];
}

void Update(int i, int x, int y, int p = 1, int L = 1, int R = m)
{
    if (i < L || i > R) return;
    if (L == R)
    {
        Seg[p].Merge(x, y);
        return;
    }
    int mid = (L + R)/2;
    Update(i, x, y, p * 2, L, mid);
    Update(i, x, y, p * 2 + 1, mid + 1, R);

    Seg[p] = Seg[p * 2] + Seg[p * 2 + 1];
}

ll Query(Node &ans, ll p = 1, ll L = 1, ll R = m)
{
    if(L == R){
        ans = ans + Seg[p];
        if(ans.comp == 1)   return Gold[L];
        else  return Inf;
    }
    int mid = (L + R)/2;
    Node foo = ans + Seg[p * 2];
    if(foo.comp == 1)  return Query(ans , p * 2 , L , mid);
    else {
        ans = foo;
        return Query(ans , p * 2 + 1 , mid + 1 , R);
    }
}

int main()
{
    cin >> n >> m >> G >> S;
    for(ll i = 0; i<m; i++)
    {
        scanf("%d%d%d%d",&edges[i].u , &edges[i].v , &edges[i].g , &edges[i].s);
        v.push_back(edges[i].g);
    }
    sort(v.begin(), v.end());
    sort(edges, edges + m, cmp);
    for(ll i = 0; i<m; i++)  Gold[Hash] = v[i] , mp[v[i]] = Hash++;
    ll Ans = Inf;
    Build();
    for(ll i = 0; i<m; i++){
        Update(mp[edges[i].g] , edges[i].u , edges[i].v);
        Node temp;
        temp.init();
        ll Res = Query(temp);
        if(Res != Inf)  Ans = min(Ans ,  (ll)edges[i].s * S + Res * G);
    }
    cout << (Ans == Inf ? -1 : Ans);
    return 0;
}


#include <iostream>
#include <bits/stdc++.h>
#define ll long long

using namespace std;
const ll N = 50100;
ll G,S,n,m,Hash = 1,Gold[N];
const ll Inf = 9e18;

struct Edge
{
    ll u,v,g,s;
} edges[50100];

bool cmp(const struct Edge &s1, const struct Edge &s2)
{
    return s1.s < s2.s;
}

struct Node
{
    ll par[210],Size[210];
    ll comp;
    void init()
    {
        for(ll i=1; i<=n; i++)  Size[i]=1,par[i]=i;
        comp = n;
    }
    ll getparent(ll x)
    {
        if(x==par[x])  return x;
        return par[x]=getparent(par[x]);
    }
    void Merge(ll x, ll y)
    {
        x = getparent(x);
        y = getparent(y);
        if(x==y)  return ;
        if(Size[x] < Size[y])  swap(x,y);
        Size[x]+=Size[y];
        par[y] = x;
        comp--;
    }
    struct Node operator +(struct Node &s)
    {
        Node temp = *this;
        for(ll i = 1; i<=n; i++)  temp.Merge(getparent(i) , s.getparent(i));
        return temp;
    }
} Seg[N * 4];

map < ll, ll > mp;
vector < ll > v;

void Build(ll p = 1, ll L = 1, ll R = N)
{
    if (L == R)
    {
        Seg[p].init();
        return;
    }
    ll mid = (L + R)/2;
    Build(p * 2, L, mid);
    Build(p * 2 + 1, mid + 1, R);

    Seg[p] = Seg[p * 2] + Seg[p * 2 + 1];
}

void Update(ll i, ll x, ll y, ll p = 1, ll L = 1, ll R = m)
{
    if (i < L || i > R) return;
    if (L == R)
    {
        Seg[p].Merge(x, y);
        return;
    }
    ll mid = (L + R)/2;
    Update(i, x, y, p * 2, L, mid);
    Update(i, x, y, p * 2 + 1, mid + 1, R);

    Seg[p] = Seg[p * 2] + Seg[p * 2 + 1];
}

ll Query(Node &ans, ll p = 1, ll L = 1, ll R = m)
{
    if(L == R){
        ans = ans + Seg[p];
        if(ans.comp == 1)   return Gold[L];
        else  return Inf;
    }
    ll mid = (L + R)/2;
    Node foo = ans + Seg[p * 2];
    if(foo.comp == 1)  return Query(ans , p * 2 , L , mid);
    else {
        ans = foo;
        return Query(ans , p * 2 + 1 , mid + 1 , R);
    }
}

int main()
{
    cin >> n >> m >> G >> S;
    for(ll i = 0; i<m; i++)
    {
        cin >> edges[i].u >> edges[i].v >> edges[i].g >> edges[i].s;
        v.push_back(edges[i].g);
    }
    sort(v.begin(), v.end());
    sort(edges, edges + m, cmp);
    for(ll i = 0; i<m; i++)  Gold[Hash] = v[i] , mp[v[i]] = Hash++;
    ll Ans = Inf;
    Build();
    Node temp;
    temp.init();
    for(ll i = 0; i<m; i++){
        Update(mp[edges[i].g] , edges[i].u , edges[i].v);
        Node temp;
        temp.init();
        ll Res = Query(temp);
        if(Res != Inf)  Ans = min(Ans , (long long) edges[i].s * S + Res * G);
    }
    cout << Ans;
    return 0;
}


#include <iostream>
#include <bits/stdc++.h>
#define ll long long

using namespace std;
const ll N = 50010;
ll G,S,n,m,Hash = 1,Gold[N];
const ll Inf = 9e18;

struct Edge
{
    ll u,v,g,s;
} edges[50100];

bool cmp(const struct Edge &s1, const struct Edge &s2)
{
    return s1.s < s2.s;
}

struct Node
{
    int par[201],Size[201];
    int comp;
    void init()
    {
        for(ll i=1; i<=n; i++)  Size[i]=1,par[i]=i;
        comp = n;
    }
    ll getparent(ll x)
    {
        if(x==par[x])  return x;
        return par[x]=getparent(par[x]);
    }
    void Merge(ll x, ll y)
    {
        x = getparent(x);
        y = getparent(y);
        if(x==y)  return ;
        if(Size[x] < Size[y])  swap(x,y);
        Size[x]+=Size[y];
        par[y] = x;
        comp--;
    }
    struct Node operator +(struct Node &s)
    {
        Node temp = *this;
        for(ll i = 1; i<=n; i++)  temp.Merge(getparent(i) , s.getparent(i));
        return temp;
    }
}Seg[N * 3];

map < ll, ll > mp;
vector < ll > v;

void Build(ll p = 1, ll L = 1, ll R = N)
{
    if (L == R)
    {
        Seg[p].init();
        return;
    }
    ll mid = (L + R)/2;
    Build(p * 2, L, mid);
    Build(p * 2 + 1, mid + 1, R);

    Seg[p] = Seg[p * 2] + Seg[p * 2 + 1];
}

void Update(ll i, ll x, ll y, ll p = 1, ll L = 1, ll R = m)
{
    if (i < L || i > R) return;
    if (L == R)
    {
        Seg[p].Merge(x, y);
        return;
    }
    ll mid = (L + R)/2;
    Update(i, x, y, p * 2, L, mid);
    Update(i, x, y, p * 2 + 1, mid + 1, R);

    Seg[p] = Seg[p * 2] + Seg[p * 2 + 1];
}

ll Query(Node &ans, ll p = 1, ll L = 1, ll R = m)
{
    if(L == R){
        ans = ans + Seg[p];
        if(ans.comp == 1)   return Gold[L];
        else  return Inf;
    }
    ll mid = (L + R)/2;
    Node foo = ans + Seg[p * 2];
    if(foo.comp == 1)  return Query(ans , p * 2 , L , mid);
    else {
        ans = foo;
        return Query(ans , p * 2 + 1 , mid + 1 , R);
    }
}

int main()
{
    cin >> n >> m >> G >> S;
    for(ll i = 0; i<m; i++)
    {
        cin >> edges[i].u >> edges[i].v >> edges[i].g >> edges[i].s;
        v.push_back(edges[i].g);
    }
    sort(v.begin(), v.end());
    sort(edges, edges + m, cmp);
    for(ll i = 0; i<m; i++)  Gold[Hash] = v[i] , mp[v[i]] = Hash++;
    ll Ans = Inf;
    Build();
    Node temp;
    temp.init();
    for(ll i = 0; i<m; i++){
        Update(mp[edges[i].g] , edges[i].u , edges[i].v);
        Node temp;
        temp.init();
        ll Res = Query(temp);
        if(Res != Inf)  Ans = min(Ans ,  edges[i].s * S + Res * G);
    }
    cout << Ans;
    return 0;
}


#include <iostream>
#include <bits/stdc++.h>
#define ll long long

using namespace std;
const int N = 50010;
int G,S,n,m,Hash = 1,Gold[N];
const ll Inf = 9e18;

struct Edge
{
    int u,v,g,s;
} edges[50100];

bool cmp(const struct Edge &s1, const struct Edge &s2)
{
    return s1.s < s2.s;
}

struct Node
{
    int par[201],Size[201];
    int comp;
    inline void init()
    {
        for(ll i=1; i<=n; i++)  Size[i]=1,par[i]=i;
        comp = n;
    }
    inline int getparent(int x)
    {
        if(x==par[x])  return x;
        return par[x]=getparent(par[x]);
    }
    inline void Merge(int x , int y)
    {
        x = getparent(x);
        y = getparent(y);
        if(x==y)  return ;
        if(Size[x] < Size[y])  swap(x,y);
        Size[x]+=Size[y];
        par[y] = x;
        comp--;
    }
    inline struct Node operator +(struct Node &s)
    {
        Node temp = *this;
        for(ll i = 1; i<=n; i++)  temp.Merge(getparent(i) , s.getparent(i));
        return temp;
    }
}Seg[N * 3];

map < int , int > mp;
vector < int > v;

void Build(int p = 1, int L = 1, int R = N)
{
    if (L == R)
    {
        Seg[p].init();
        return;
    }
    int mid = (L + R)/2;
    Build(p * 2, L, mid);
    Build(p * 2 + 1, mid + 1, R);

    Seg[p] = Seg[p * 2] + Seg[p * 2 + 1];
}

void Update(int i, int x, int y, int p = 1, int L = 1, int R = m)
{
    if (i < L || i > R) return;
    if (L == R)
    {
        Seg[p].Merge(x, y);
        return;
    }
    int mid = (L + R)/2;
    Update(i, x, y, p * 2, L, mid);
    Update(i, x, y, p * 2 + 1, mid + 1, R);

    Seg[p] = Seg[p * 2] + Seg[p * 2 + 1];
}

ll Query(Node &ans, ll p = 1, ll L = 1, ll R = m)
{
    if(L == R){
        ans = ans + Seg[p];
        if(ans.comp == 1)   return Gold[L];
        else  return Inf;
    }
    int mid = (L + R)/2;
    Node foo = ans + Seg[p * 2];
    if(foo.comp == 1)  return Query(ans , p * 2 , L , mid);
    else {
        ans = foo;
        return Query(ans , p * 2 + 1 , mid + 1 , R);
    }
}

int main()
{
    cin >> n >> m >> G >> S;
    for(ll i = 0; i<m; i++)
    {
        scanf("%d%d%d%d",&edges[i].u , &edges[i].v , &edges[i].g , &edges[i].s);
        v.push_back(edges[i].g);
    }
    sort(v.begin(), v.end());
    sort(edges, edges + m, cmp);
    for(ll i = 0; i<m; i++)  Gold[Hash] = v[i] , mp[v[i]] = Hash++;
    ll Ans = Inf;
    Build();
    for(ll i = 0; i<m; i++){
        int idx = mp[edges[i].g];
        Update(idx , edges[i].u , edges[i].v);
        Node temp;
        temp.init();
        ll Res = Query(temp);
        if(Res != Inf)  Ans = min(Ans ,  (ll)edges[i].s * S + Res * G);
    }
    cout << (Ans == Inf ? -1 : Ans);
    return 0;
}


#include <iostream>
#include <bits/stdc++.h>
#define ll long long

using namespace std;
const int N = 50010;
int G,S,n,m,Hash = 1,Gold[N];
const ll Inf = 9e18;

struct Edge
{
    int u,v,g,s;
} edges[50100];

bool cmp(const struct Edge &s1, const struct Edge &s2)
{
    return s1.s < s2.s;
}

struct Node
{
    int par[201],Size[201];
    int comp;
    void init()
    {
        for(ll i=1; i<=n; i++)  Size[i]=1,par[i]=i;
        comp = n;
    }
    int getparent(ll x)
    {
        if(x==par[x])  return x;
        return par[x]=getparent(par[x]);
    }
    void Merge(ll x, ll y)
    {
        x = getparent(x);
        y = getparent(y);
        if(x==y)  return ;
        if(Size[x] < Size[y])  swap(x,y);
        Size[x]+=Size[y];
        par[y] = x;
        comp--;
    }
    struct Node operator +(struct Node &s)
    {
        Node temp = *this;
        for(ll i = 1; i<=n; i++)  temp.Merge(getparent(i) , s.getparent(i));
        return temp;
    }
}Seg[N * 3];

map < int , int > mp;
vector < int > v;

void Build(int p = 1, int L = 1, int R = N)
{
    if (L == R)
    {
        Seg[p].init();
        return;
    }
    int mid = (L + R)/2;
    Build(p * 2, L, mid);
    Build(p * 2 + 1, mid + 1, R);

    Seg[p] = Seg[p * 2] + Seg[p * 2 + 1];
}

void Update(int i, int x, int y, int p = 1, int L = 1, int R = m)
{
    if (i < L || i > R) return;
    if (L == R)
    {
        Seg[p].Merge(x, y);
        return;
    }
    int mid = (L + R)/2;
    Update(i, x, y, p * 2, L, mid);
    Update(i, x, y, p * 2 + 1, mid + 1, R);

    Seg[p] = Seg[p * 2] + Seg[p * 2 + 1];
}

ll Query(Node &ans, ll p = 1, ll L = 1, ll R = m)
{
    if(L == R){
        ans = ans + Seg[p];
        if(ans.comp == 1)   return Gold[L];
        else  return Inf;
    }
    int mid = (L + R)/2;
    Node foo = ans + Seg[p * 2];
    if(foo.comp == 1)  return Query(ans , p * 2 , L , mid);
    else {
        ans = foo;
        return Query(ans , p * 2 + 1 , mid + 1 , R);
    }
}

int main()
{
    cin >> n >> m >> G >> S;
    for(ll i = 0; i<m; i++)
    {
        scanf("%d%d%d%d",&edges[i].u , &edges[i].v , &edges[i].g , &edges[i].s);
        v.push_back(edges[i].g);
    }
    sort(v.begin(), v.end());
    sort(edges, edges + m, cmp);
    for(ll i = 0; i<m; i++)  Gold[Hash] = v[i] , mp[v[i]] = Hash++;
    ll Ans = Inf;
    Build();
    Node temp;
    temp.init();
    for(ll i = 0; i<m; i++){
        Update(mp[edges[i].g] , edges[i].u , edges[i].v);
        Node temp;
        temp.init();
        ll Res = Query(temp);
        if(Res != Inf)  Ans = min(Ans ,  (ll)edges[i].s * S + Res * G);
    }
    cout << (Ans == Inf ? -1 : Ans);
    return 0;
}


#include <iostream>
#include <bits/stdc++.h>
#define ll long long

using namespace std;
const int N = 50010;
int G,S,n,m,Hash = 1,Gold[N];
const ll Inf = 9e18;

struct Edge
{
    int u,v,g,s;
} edges[50100];

bool cmp(const struct Edge &s1, const struct Edge &s2)
{
    return s1.s < s2.s;
}

struct Node
{
    int par[201],Size[201];
    int comp;
    inline void init()
    {
        for(ll i=1; i<=n; i++)  Size[i]=1,par[i]=i;
        comp = n;
    }
    inline int getparent(int x)
    {
        if(x==par[x])  return x;
        return par[x]=getparent(par[x]);
    }
    inline void Merge(int x , int y)
    {
        x = getparent(x);
        y = getparent(y);
        if(x==y)  return ;
        if(Size[x] < Size[y])  swap(x,y);
        Size[x]+=Size[y];
        par[y] = x;
        comp--;
    }
    inline struct Node operator +(struct Node &s)
    {
        Node temp = *this;
        for(ll i = 1; i<=n; i++)  temp.Merge(getparent(i) , s.getparent(i));
        return temp;
    }
}Seg[N * 3];

unordered_map < int , int > mp;
vector < int > v;

void Build(int p = 1, int L = 1, int R = N)
{
    if (L == R)
    {
        Seg[p].init();
        return;
    }
    int mid = (L + R)/2;
    Build(p * 2, L, mid);
    Build(p * 2 + 1, mid + 1, R);

    Seg[p] = Seg[p * 2] + Seg[p * 2 + 1];
}

void Update(int i, int x, int y, Node Now , int p = 1, int L = 1, int R = m)
{
    if (i < L || i > R) return;
    if (L == R)
    {
        Seg[p].Merge(x, y);
        return;
    }
    int mid = (L + R)/2;
    Update(i, x, y, Now , p * 2, L, mid);
    Update(i, x, y, Now , p * 2 + 1, mid + 1, R);

    Seg[p].Merge(Seg[p * 2].getparent(x) , Seg[p * 2 + 1].getparent(x));
    Seg[p].Merge(Seg[p * 2].getparent(y) , Seg[p * 2 + 1].getparent(y));
}

ll Query(Node &ans, ll p = 1, ll L = 1, ll R = m)
{
    if(L == R){
        ans = ans + Seg[p];
        if(ans.comp == 1)   return Gold[L];
        else  return Inf;
    }
    int mid = (L + R)/2;
    Node foo = ans + Seg[p * 2];
    if(foo.comp == 1)  return Query(ans , p * 2 , L , mid);
    else {
        ans = foo;
        return Query(ans , p * 2 + 1 , mid + 1 , R);
    }
}

int main()
{
    cin >> n >> m >> G >> S;
    for(ll i = 0; i<m; i++)
    {
        scanf("%d%d%d%d",&edges[i].u , &edges[i].v , &edges[i].g , &edges[i].s);
        v.push_back(edges[i].g);
    }
    sort(v.begin(), v.end());
    sort(edges, edges + m, cmp);
    for(ll i = 0; i<m; i++)  Gold[Hash] = v[i] , mp[v[i]] = Hash++;
    ll Ans = Inf;
    Build();
    for(ll i = 0; i<m; i++){
        Node temp;
        temp.init();
        Update(mp[edges[i].g] , edges[i].u , edges[i].v , temp);
        temp.init();
        ll Res = Query(temp);
        if(Res != Inf)  Ans = min(Ans ,  (ll)edges[i].s * S + Res * G);
    }
    cout << (Ans == Inf ? -1 : Ans);
    return 0;
}


#include <iostream>
#include <bits/stdc++.h>
#define ll long long

using namespace std;
const ll N = 50010;
ll G,S,n,m,Hash = 1,Gold[N];
const ll Inf = 9e18;

struct Edge
{
    ll u,v,g,s;
} edges[50100];

bool cmp(const struct Edge &s1, const struct Edge &s2)
{
    return s1.s < s2.s;
}

struct Node
{
    int par[201],Size[201];
    int comp;
    void init()
    {
        for(ll i=1; i<=n; i++)  Size[i]=1,par[i]=i;
        comp = n;
    }
    ll getparent(ll x)
    {
        if(x==par[x])  return x;
        return par[x]=getparent(par[x]);
    }
    void Merge(ll x, ll y)
    {
        x = getparent(x);
        y = getparent(y);
        if(x==y)  return ;
        if(Size[x] < Size[y])  swap(x,y);
        Size[x]+=Size[y];
        par[y] = x;
        comp--;
    }
    struct Node operator +(struct Node &s)
    {
        Node temp = *this;
        for(ll i = 1; i<=n; i++)  temp.Merge(getparent(i) , s.getparent(i));
        return temp;
    }
}Seg[N * 3];

map < ll, ll > mp;
vector < ll > v;

void Build(ll p = 1, ll L = 1, ll R = N)
{
    if (L == R)
    {
        Seg[p].init();
        return;
    }
    ll mid = (L + R)/2;
    Build(p * 2, L, mid);
    Build(p * 2 + 1, mid + 1, R);

    Seg[p] = Seg[p * 2] + Seg[p * 2 + 1];
}

void Update(ll i, ll x, ll y, ll p = 1, ll L = 1, ll R = m)
{
    if (i < L || i > R) return;
    if (L == R)
    {
        Seg[p].Merge(x, y);
        return;
    }
    ll mid = (L + R)/2;
    Update(i, x, y, p * 2, L, mid);
    Update(i, x, y, p * 2 + 1, mid + 1, R);

    Seg[p] = Seg[p * 2] + Seg[p * 2 + 1];
}

ll Query(Node &ans, ll p = 1, ll L = 1, ll R = m)
{
    if(L == R){
        ans = ans + Seg[p];
        if(ans.comp == 1)   return Gold[L];
        else  return Inf;
    }
    ll mid = (L + R)/2;
    Node foo = ans + Seg[p * 2];
    if(foo.comp == 1)  return Query(ans , p * 2 , L , mid);
    else {
        ans = foo;
        return Query(ans , p * 2 + 1 , mid + 1 , R);
    }
}

int main()
{
    cin >> n >> m >> G >> S;
    for(ll i = 0; i<m; i++)
    {
        cin >> edges[i].u >> edges[i].v >> edges[i].g >> edges[i].s;
        v.push_back(edges[i].g);
    }
    sort(v.begin(), v.end());
    sort(edges, edges + m, cmp);
    for(ll i = 0; i<m; i++)  Gold[Hash] = v[i] , mp[v[i]] = Hash++;
    ll Ans = Inf;
    Build();
    Node temp;
    temp.init();
    for(ll i = 0; i<m; i++){
        Update(mp[edges[i].g] , edges[i].u , edges[i].v);
        Node temp;
        temp.init();
        ll Res = Query(temp);
        if(Res != Inf)  Ans = min(Ans ,  edges[i].s * S + Res * G);
    }
    cout << (Ans == Inf ? -1 : Ans);
    return 0;
}


#include <iostream>
#include <bits/stdc++.h>
#define ll long long

using namespace std;
const int N = 50010;
int G,S,n,m,Hash = 1,Gold[N];
const ll Inf = 9e18;

struct Edge
{
    int u,v,g,s;
} edges[50100];

bool cmp(const struct Edge &s1, const struct Edge &s2)
{
    return s1.s < s2.s;
}

struct Node
{
    int par[201],Size[201];
    int comp;
    void init()
    {
        for(ll i=1; i<=n; i++)  Size[i]=1,par[i]=i;
        comp = n;
    }
    int getparent(int x)
    {
        if(x==par[x])  return x;
        return par[x]=getparent(par[x]);
    }
    void Merge(int x , int y)
    {
        x = getparent(x);
        y = getparent(y);
        if(x==y)  return ;
        if(Size[x] < Size[y])  swap(x,y);
        Size[x]+=Size[y];
        par[y] = x;
        comp--;
    }
    struct Node operator +(struct Node &s)
    {
        Node temp = *this;
        for(ll i = 1; i<=n; i++)  temp.Merge(getparent(i) , s.getparent(i));
        return temp;
    }
}Seg[N * 3];

map < int , int > mp;
vector < int > v;

void Build(int p = 1, int L = 1, int R = N)
{
    if (L == R)
    {
        Seg[p].init();
        return;
    }
    int mid = (L + R)/2;
    Build(p * 2, L, mid);
    Build(p * 2 + 1, mid + 1, R);

    Seg[p] = Seg[p * 2] + Seg[p * 2 + 1];
}

void Update(int i, int x, int y, int p = 1, int L = 1, int R = m)
{
    if (i < L || i > R) return;
    if (L == R)
    {
        Seg[p].Merge(x, y);
        return;
    }
    int mid = (L + R)/2;
    Update(i, x, y, p * 2, L, mid);
    Update(i, x, y, p * 2 + 1, mid + 1, R);

    Seg[p] = Seg[p * 2] + Seg[p * 2 + 1];
}

ll Query(Node &ans, ll p = 1, ll L = 1, ll R = m)
{
    if(L == R){
        ans = ans + Seg[p];
        if(ans.comp == 1)   return Gold[L];
        else  return Inf;
    }
    int mid = (L + R)/2;
    Node foo = ans + Seg[p * 2];
    if(foo.comp == 1)  return Query(ans , p * 2 , L , mid);
    else {
        ans = foo;
        return Query(ans , p * 2 + 1 , mid + 1 , R);
    }
}

int main()
{
    cin >> n >> m >> G >> S;
    for(ll i = 0; i<m; i++)
    {
        scanf("%d%d%d%d",&edges[i].u , &edges[i].v , &edges[i].g , &edges[i].s);
        v.push_back(edges[i].g);
    }
    sort(v.begin(), v.end());
    sort(edges, edges + m, cmp);
    for(ll i = 0; i<m; i++)  Gold[Hash] = v[i] , mp[v[i]] = Hash++;
    ll Ans = Inf;
    Build();
    for(ll i = 0; i<m; i++){
        int idx = mp[edges[i].g];
        Update(idx , edges[i].u , edges[i].v);
        Node temp;
        temp.init();
        ll Res = Query(temp);
        if(Res != Inf)  Ans = min(Ans ,  (ll)edges[i].s * S + Res * G);
    }
    cout << (Ans == Inf ? -1 : Ans);
    return 0;
}


#include <iostream>
#include <bits/stdc++.h>
#define ll long long

using namespace std;
const ll N = 50010;
ll G,S,n,m,Hash = 1,Gold[N];
const ll Inf = 9e18;

struct Edge
{
    ll u,v,g,s;
} edges[50100];

bool cmp(const struct Edge &s1, const struct Edge &s2)
{
    return s1.s < s2.s;
}

struct Node
{
    int par[201],Size[201];
    int comp;
    void init()
    {
        for(ll i=1; i<=n; i++)  Size[i]=1,par[i]=i;
        comp = n;
    }
    ll getparent(ll x)
    {
        if(x==par[x])  return x;
        return par[x]=getparent(par[x]);
    }
    void Merge(ll x, ll y)
    {
        x = getparent(x);
        y = getparent(y);
        if(x==y)  return ;
        if(Size[x] < Size[y])  swap(x,y);
        Size[x]+=Size[y];
        par[y] = x;
        comp--;
    }
    struct Node operator +(struct Node &s)
    {
        Node temp = *this;
        for(ll i = 1; i<=n; i++)  temp.Merge(getparent(i) , s.getparent(i));
        return temp;
    }
}Seg[N * 3];

map < ll, ll > mp;
vector < ll > v;

void Build(ll p = 1, ll L = 1, ll R = N)
{
    if (L == R)
    {
        Seg[p].init();
        return;
    }
    ll mid = (L + R)/2;
    Build(p * 2, L, mid);
    Build(p * 2 + 1, mid + 1, R);

    Seg[p] = Seg[p * 2] + Seg[p * 2 + 1];
}

void Update(ll i, ll x, ll y, ll p = 1, ll L = 1, ll R = m)
{
    if (i < L || i > R) return;
    if (L == R)
    {
        Seg[p].Merge(x, y);
        return;
    }
    ll mid = (L + R)/2;
    Update(i, x, y, p * 2, L, mid);
    Update(i, x, y, p * 2 + 1, mid + 1, R);

    Seg[p] = Seg[p * 2] + Seg[p * 2 + 1];
}

ll Query(Node &ans, ll p = 1, ll L = 1, ll R = m)
{
    if(L == R){
        ans = ans + Seg[p];
        if(ans.comp == 1)   return Gold[L];
        else  return Inf;
    }
    ll mid = (L + R)/2;
    Node foo = ans + Seg[p * 2];
    if(foo.comp == 1)  return Query(ans , p * 2 , L , mid);
    else {
        ans = foo;
        return Query(ans , p * 2 + 1 , mid + 1 , R);
    }
}

int main()
{
    cin >> n >> m >> G >> S;
    for(ll i = 0; i<m; i++)
    {
        scanf("%I64d%I64d%I64d%I64d",&edges[i].u , &edges[i].v , &edges[i].g , &edges[i].s);
        v.push_back(edges[i].g);
    }
    sort(v.begin(), v.end());
    sort(edges, edges + m, cmp);
    for(ll i = 0; i<m; i++)  Gold[Hash] = v[i] , mp[v[i]] = Hash++;
    ll Ans = Inf;
    Build();
    Node temp;
    temp.init();
    for(ll i = 0; i<m; i++){
        Update(mp[edges[i].g] , edges[i].u , edges[i].v);
        Node temp;
        temp.init();
        ll Res = Query(temp);
        if(Res != Inf)  Ans = min(Ans ,  edges[i].s * S + Res * G);
    }
    cout << (Ans == Inf ? -1 : Ans);
    return 0;
}


#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
#include<set>
#include<cmath>
#include<string>
#include<map>
#include<vector>
#include<ctime>
#include<stack>
using namespace std;
#define mm(a,b) memset(a,b,sizeof(a))
typedef long long ll;
typedef unsigned long long ull;
const long long mod = 1e9 + 7;
const int maxn = 5e4+100;
const ll inf = 0x3f3f3f3f3f3f3f3f;
int n,m,G,S;
struct node{
    int u;
    int v;
    ll g,s;
};
node st[maxn],road[maxn];
int vis[maxn];
ll ans=0,cnt=0;
bool cmp(node a,node b){
    if(a.g==b.g)
        return a.s<b.s;
    return a.g<b.g;
}
bool cmp1(node a,node b){
    return a.s<b.s;
}
int find(int x){
    if(vis[x]!=x)
        return vis[x]=find(vis[x]);
    return vis[x];
}
void kruskal(){
    int tmp=1;
    ans=inf;
    for(int i=1;i<=m;i++){
        for(int j=1;j<=n;j++)
            vis[j]=j;
        st[tmp++]=road[i];
        ll maxx=0;
        int t=1;
        sort(st,st+tmp,cmp1);
        for(int j=1;j<=tmp;j++){
            int u=find(st[j].u);
            int v=find(st[j].v);
            if(u!=v){
                maxx=max(maxx,st[j].s);
                st[t++]=st[j];
                vis[u]=v;
            }
            if(t==n) break;
        }
        if(t==n)
            ans=min(ans,road[i].g*G+maxx*S);
        tmp=t;
    }
}
int main()
{
    scanf("%d %d",&n,&m);
    scanf("%d %d",&G,&S);
    for(int i=1;i<=m;i++){
        scanf("%d %d %lld %lld",&road[i].u,&road[i].v,&road[i].g,&road[i].s);
    }
    sort(road+1,road+1+m,cmp);
    kruskal();
    if(ans!=inf)
        printf("%lld\n",ans);
    else
        puts("-1");
}


#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
#include<set>
#include<cmath>
#include<string>
#include<map>
#include<vector>
#include<ctime>
#include<stack>
using namespace std;
#define mm(a,b) memset(a,b,sizeof(a))
typedef long long ll;
typedef unsigned long long ull;
const long long mod = 1e9 + 7;
const int maxn = 5e4+100;
const int inf = 0x3f3f3f3f;
int n;
int mini=inf;
struct node{
    int next;
    int v;
    ll number[2];
    ll cost;
    friend bool operator < (node a,node b){
        if(a.number[0]==b.number[0])
            return a.number[1]>b.number[1];
        return a.number[0]>b.number[0];
    }
}road[maxn];
int head[300],cnt=0;
int vis[300];
void add_edge(int u,int v,ll g,ll s,ll cost){
    road[cnt].v=v;
    road[cnt].number[0]=g;
    road[cnt].number[1]=s;
    road[cnt].next=head[u];
    road[cnt].cost=cost;
    head[u]=cnt++;
}
ll ans=0,g_num=0,s_num=0;
int sum=1;
priority_queue<node> q;
void work(int u){
    while(!q.empty()){
        q.pop();
    }
    for(int i=head[u];i!=-1;i=road[i].next){
        q.push(road[i]);
    }
    vis[u]=1;
    while(!q.empty()&&sum!=n){
        node temp=q.top();
        q.pop();
        int v=temp.v;
        if(!vis[v]){
            g_num=max(g_num,temp.number[0]);
            s_num=max(s_num,temp.number[1]);
            vis[v]=1;
            sum++;
            for(int i=head[v];i!=-1;i=road[i].next){
                if(!vis[road[i].v]){
                    q.push(road[i]);
                }
            }

        }
    }
}
int main()
{
    mm(vis,0);
    mm(head,-1);
    cnt=0;
    sum=1;
    g_num=0,s_num=0,ans=0;
    int n,m;
    scanf("%d %d",&n,&m);
    ll G,S;
    int start=1;
    ll tmp=inf;
    scanf("%lld %lld",&G,&S);
    if(G>S)
        mini=0;
    else
        mini=1;
    while(m--){
        int u,v;
        ll g,s;
        scanf("%d %d %lld %lld",&u,&v,&g,&s);
        if(u==v)
            continue;
        //if(tmp>g*G+s*S){
        //  tmp=g*G+s*S;
        //start=u;
        //}
        add_edge(u,v,g,s,g*G+s*S);
        add_edge(v,u,g,s,g*G+s*S);
    }
    work(start);
    if(sum==n)
        printf("%lld\n",g_num*G+s_num*S);
    else
        puts("-1");
}


#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
#include<set>
#include<cmath>
#include<string>
#include<map>
#include<vector>
#include<ctime>
#include<stack>
using namespace std;
#define mm(a,b) memset(a,b,sizeof(a))
typedef long long ll;
typedef unsigned long long ull;
const long long mod = 1e9 + 7;
const int maxn = 5e4+100;
const int inf = 0x3f3f3f3f;
int n;
struct node{
    int next;
    int v;
    ll g,s;
    ll cost;
    friend bool operator < (node a,node b){
        return a.cost>b.cost;
    }
}road[maxn];
int head[300],cnt=0;
int vis[300];
void add_edge(int u,int v,ll g,ll s,ll cost){
    road[cnt].v=v;
    road[cnt].g=g;
    road[cnt].s=s;
    road[cnt].next=head[u];
    road[cnt].cost=cost;
    head[u]=cnt++;
}
ll ans=0,g_num=0,s_num=0;
int sum=1;
priority_queue<node> q;
void work(int u){
    while(!q.empty()){
        q.pop();
    }
    for(int i=head[u];i!=-1;i=road[i].next){
        q.push(road[i]);
    }
    vis[u]=1;
    while(!q.empty()&&sum!=n){
        node temp=q.top();
        q.pop();
        int v=temp.v;
        if(!vis[v]){
            g_num=max(g_num,temp.g);
            s_num=max(s_num,temp.s);
            vis[v]=1;
            sum++;
            for(int i=head[v];i!=-1;i=road[i].next){
                if(!vis[road[i].v]){
                    q.push(road[i]);
                }
            }

        }
    }
}
int main()
{
    mm(vis,0);
    mm(head,-1);
    mm(in,0);
    cnt=0;
    sum=1;
    g_num=0,s_num=0,ans=0;
    int n,m;
    scanf("%d %d",&n,&m);
    ll G,S;
    int start=0;
    ll tmp=inf;
    scanf("%lld %lld",&G,&S);
    while(m--){
        int u,v;
        ll g,s;
        scanf("%d %d %lld %lld",&u,&v,&g,&s);
        if(u==v)
            continue;
        if(tmp>g*G+s*S){
            tmp=g*G+s*S;
            start=u;
        }
        add_edge(u,v,g,s,g*G+s*S);
        add_edge(v,u,g,s,g*G+s*S);
    }
    work(start);
    if(sum==n)
        printf("%lld\n",g_num*G+s_num*S);
    else
        puts("-1");
}


#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
#include<set>
#include<cmath>
#include<string>
#include<map>
#include<vector>
#include<ctime>
#include<stack>
using namespace std;
#define mm(a,b) memset(a,b,sizeof(a))
typedef long long ll;
typedef unsigned long long ull;
const long long mod = 1e9 + 7;
const int maxn = 5e4+100;
const int inf = 0x3f3f3f3f;
int n;
struct node{
    int next;
    int v;
    ll g,s;
    ll cost;
    friend bool operator < (node a,node b){
        return a.cost>b.cost;
    }
}road[maxn];
int head[300],cnt=0;
int vis[300];
void add_edge(int u,int v,ll g,ll s,ll cost){
    road[cnt].v=v;
    road[cnt].g=g;
    road[cnt].s=s;
    road[cnt].next=head[u];
    road[cnt].cost=cost;
    head[u]=cnt++;
}
ll ans=0,g_num=0,s_num=0;
int sum=1;
priority_queue<node> q;
void work(){
    while(!q.empty()){
        q.pop();
    }
    for(int i=head[1];i!=-1;i=road[i].next){
        q.push(road[i]);
    }
    vis[1]=1;
    while(!q.empty()&&sum!=n){
        node temp=q.top();
        q.pop();
        int v=temp.v;
        if(!vis[v]){
            g_num=max(g_num,temp.g);
            s_num=max(s_num,temp.s);
            vis[v]=1;
            sum++;
            for(int i=head[v];i!=-1;i=road[i].next){
                if(!vis[road[i].v]){
                    q.push(road[i]);
                }
            }

        }
    }
}
int main()
{
    mm(vis,0);
    mm(head,-1);
    cnt=0;
    sum=1;
    g_num=0,s_num=0,ans=0;
    int n,m;
    scanf("%d %d",&n,&m);
    ll G,S;
    scanf("%lld %lld",&G,&S);
    while(m--){
        int u,v;
        ll g,s;
        scanf("%d %d %lld %lld",&u,&v,&g,&s);
        if(u==v)
            continue;
        add_edge(u,v,g,s,g*G+s*S);
        add_edge(v,u,g,s,g*G+s*S);
    }
    work();
    if(sum!=n)
        printf("%lld\n",g_num*G+s_num*S);
    else
        puts("-1");
}


#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
#include<set>
#include<cmath>
#include<string>
#include<map>
#include<vector>
#include<ctime>
#include<stack>
using namespace std;
#define mm(a,b) memset(a,b,sizeof(a))
typedef long long ll;
typedef unsigned long long ull;
const long long mod = 1e9 + 7;
const int maxn = 5e4+100;
const int inf = 0x3f3f3f3f;
int n;
struct node{
    int next;
    int v;
    ll g,s;
    ll cost;
    friend bool operator < (node a,node b){
        return a.cost>b.cost;
    }
}road[maxn];
int head[300],cnt=0;
int vis[300];
void add_edge(int u,int v,ll g,ll s,ll cost){
    road[cnt].v=v;
    road[cnt].g=g;
    road[cnt].s=s;
    road[cnt].next=head[u];
    road[cnt].cost=cost;
    head[u]=cnt++;
}
ll ans=0,g_num=0,s_num=0;
int sum=1;
priority_queue<node> q;
void work(int u){
    while(!q.empty()){
        q.pop();
    }
    for(int i=head[u];i!=-1;i=road[i].next){
        q.push(road[i]);
    }
    vis[u]=1;
    while(!q.empty()&&sum!=n){
        node temp=q.top();
        q.pop();
        int v=temp.v;
        if(!vis[v]){
            g_num=max(g_num,temp.g);
            s_num=max(s_num,temp.s);
            vis[v]=1;
            sum++;
            for(int i=head[v];i!=-1;i=road[i].next){
                if(!vis[road[i].v]){
                    q.push(road[i]);
                }
            }

        }
    }
}
int main()
{
    mm(vis,0);
    mm(head,-1);
    cnt=0;
    sum=1;
    g_num=0,s_num=0,ans=0;
    int n,m;
    scanf("%d %d",&n,&m);
    ll G,S;
    int start=0;
    ll tmp=inf;
    scanf("%lld %lld",&G,&S);
    while(m--){
        int u,v;
        ll g,s;
        scanf("%d %d %lld %lld",&u,&v,&g,&s);
        if(u==v)
            continue;
        if(tmp>g*G+s*S){
            tmp=g*G+s*S;
            start=u;
        }
        add_edge(u,v,g,s,g*G+s*S);
        add_edge(v,u,g,s,g*G+s*S);
    }
    work(start);
    if(sum==n)
        printf("%lld\n",g_num*G+s_num*S);
    else
        puts("-1");
}


#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
#include<set>
#include<cmath>
#include<string>
#include<map>
#include<vector>
#include<ctime>
#include<stack>
using namespace std;
#define mm(a,b) memset(a,b,sizeof(a))
typedef long long ll;
typedef unsigned long long ull;
const long long mod = 1e9 + 7;
const int maxn = 5e4+100;
const int inf = 0x3f3f3f3f;
int n;
int mini=inf;
struct node{
    int next;
    int v;
    ll number[2];
    ll cost;
    friend bool operator < (node a,node b){
        return a.number[mini]>b.number[mini];
    }
}road[maxn];
int head[300],cnt=0;
int vis[300];
void add_edge(int u,int v,ll g,ll s,ll cost){
    road[cnt].v=v;
    road[cnt].number[0]=g;
    road[cnt].number[1]=s;
    road[cnt].next=head[u];
    road[cnt].cost=cost;
    head[u]=cnt++;
}
ll ans=0,g_num=0,s_num=0;
int sum=1;
priority_queue<node> q;
void work(int u){
    while(!q.empty()){
        q.pop();
    }
    for(int i=head[u];i!=-1;i=road[i].next){
        q.push(road[i]);
    }
    vis[u]=1;
    while(!q.empty()&&sum!=n){
        node temp=q.top();
        q.pop();
        int v=temp.v;
        if(!vis[v]){
            g_num=max(g_num,temp.number[0]);
            s_num=max(s_num,temp.number[1]);
            vis[v]=1;
            sum++;
            for(int i=head[v];i!=-1;i=road[i].next){
                if(!vis[road[i].v]){
                    q.push(road[i]);
                }
            }

        }
    }
}
int main()
{
    mm(vis,0);
    mm(head,-1);
    cnt=0;
    sum=1;
    g_num=0,s_num=0,ans=0;
    int n,m;
    scanf("%d %d",&n,&m);
    ll G,S;
    int start=1;
    ll tmp=inf;
    scanf("%lld %lld",&G,&S);
    if(G>S)
        mini=0;
    else
        mini=1;
    while(m--){
        int u,v;
        ll g,s;
        scanf("%d %d %lld %lld",&u,&v,&g,&s);
        if(u==v)
            continue;
        //if(tmp>g*G+s*S){
          //  tmp=g*G+s*S;
            //start=u;
        //}
        add_edge(u,v,g,s,g*G+s*S);
        add_edge(v,u,g,s,g*G+s*S);
    }
    work(start);
    if(sum==n)
        printf("%lld\n",g_num*G+s_num*S);
    else
        puts("-1");
}


#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
#include<set>
#include<cmath>
#include<string>
#include<map>
#include<vector>
#include<ctime>
#include<stack>
using namespace std;
#define mm(a,b) memset(a,b,sizeof(a))
typedef long long ll;
typedef unsigned long long ull;
const long long mod = 1e9 + 7;
const int maxn = 5e4+100;
const ll inf = 0x3f3f3f3f3f3f3f3f;
int n,m,G,S;
struct node{
    int u;
    int v;
    ll g,s;
};
node st[maxn],road[maxn];
int vis[maxn];
ll ans=0,cnt=0;
bool cmp(node a,node b){
    if(a.g==b.g)
        return a.s<b.s;
    return a.g<b.g;
}
bool cmp1(node a,node b){
    return a.s<b.s;
}
int find(int x){
    if(vis[x]!=x)
        return vis[x]=find(vis[x]);
    return vis[x];
}
void kruskal(){
    int tmp=0;
    ans=0x3f3f3f3f3f3f3f3fll;
    for(int i=0;i<m;i++){
        for(int j=1;j<=n;j++)
            vis[j]=j;
        st[tmp++]=road[i];
        ll maxx=0;
        int t=0;
        sort(st,st+tmp,cmp1);
        for(int j=0;j<tmp;j++){
            int u=find(st[j].u);
            int v=find(st[j].v);
            if(u!=v){
                maxx=max(maxx,st[j].s);
                st[t++]=st[j];
                vis[u]=v;
            }
            if(t==n-1) break;
        }
        if(t==n-1)
            ans=min(ans,road[i].g*G+maxx*S);
        tmp=t;
    }
}
int main()
{
    scanf("%d %d",&n,&m);
    scanf("%d %d",&G,&S);
    for(int i=0;i<m;i++){
        scanf("%d %d %lld %lld",&road[i].u,&road[i].v,&road[i].g,&road[i].s);
    }
    sort(road,road+m,cmp);
    kruskal();
    if(ans!=0x3f3f3f3f3f3f3f3fll)
        printf("%lld\n",ans);
    else
        puts("-1");
}


#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
#include<set>
#include<cmath>
#include<string>
#include<map>
#include<vector>
#include<ctime>
#include<stack>
using namespace std;
#define mm(a,b) memset(a,b,sizeof(a))
typedef long long ll;
typedef unsigned long long ull;
const long long mod = 1e9 + 7;
const int maxn = 5e4+100;
const ll inf = 0x3f3f3f3f3f3f3f3f;
int n,m,G,S;
struct node{
    int u;
    int v;
    ll g,s;
};
node st[maxn],road[maxn];
int vis[maxn];
ll ans=0,cnt=0;
bool cmp(node a,node b){
    if(a.g==b.g)
        return a.s<b.s;
    return a.g<b.g;
}
bool cmp1(node a,node b){
    return a.s<b.s;
}
int find(int x){
    if(vis[x]!=x)
        return vis[x]=find(vis[x]);
    return vis[x];
}
void kruskal(){
    int tmp=0;
    ans=inf;
    for(int i=0;i<m;i++){
        for(int j=1;j<=n;j++)
            vis[j]=j;
        st[tmp++]=road[i];
        ll maxx=0;
        int t=0;
        sort(st,st+tmp,cmp1);
        for(int j=0;j<tmp;j++){
            int u=find(st[j].u);
            int v=find(st[j].v);
            if(u!=v){
                maxx=max(maxx,st[j].s);
                st[t++]=road[j];
                vis[u]=v;
            }
            if(t==n-1) break;
        }
        if(t==n-1)
            ans=min(ans,road[i].g*G+maxx*S);
        tmp=t;
    }
}
int main()
{
    scanf("%d %d",&n,&m);
    scanf("%d %d",&G,&S);
    for(int i=0;i<m;i++){
        scanf("%d %d %lld %lld",&road[i].u,&road[i].v,&road[i].g,&road[i].s);
    }
    sort(road,road+m,cmp);
    kruskal();
    if(ans!=inf)
        printf("%lld\n",ans);
    else
        puts("-1");
}


#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
#include<set>
#include<cmath>
#include<string>
#include<map>
#include<vector>
#include<ctime>
#include<stack>
using namespace std;
#define mm(a,b) memset(a,b,sizeof(a))
typedef long long ll;
typedef unsigned long long ull;
const long long mod = 1e9 + 7;
const int maxn = 5e4+100;
const int inf = 0x3f3f3f3f;
int n;
struct node{
    int next;
    int v;
    ll g,s;
    ll cost;
    friend bool operator < (node a,node b){
        return a.cost>b.cost;
    }
}road[maxn];
int head[300],cnt=0;
int vis[300];
void add_edge(int u,int v,ll g,ll s,ll cost){
    road[cnt].v=v;
    road[cnt].g=g;
    road[cnt].s=s;
    road[cnt].next=head[u];
    road[cnt].cost=cost;
    head[u]=cnt++;
}
ll ans=0,g_num=0,s_num=0;
int sum=1;
priority_queue<node> q;
void work(){
    while(!q.empty()){
        q.pop();
    }
    for(int i=head[1];i!=-1;i=road[i].next){
        q.push(road[i]);
    }
    vis[1]=1;
    while(!q.empty()&&sum!=n){
        node temp=q.top();
        q.pop();
        int v=temp.v;
        if(!vis[v]){
            g_num=max(g_num,temp.g);
            s_num=max(s_num,temp.s);
            vis[v]=1;
            sum++;
            for(int i=head[v];i!=-1;i=road[i].next){
                if(!vis[road[i].v]){
                    q.push(road[i]);
                }
            }

        }
    }
}
int main()
{
    mm(vis,0);
    mm(head,-1);
    cnt=0;
    sum=1;
    g_num=0,s_num=0,ans=0;
    int n,m;
    scanf("%d %d",&n,&m);
    ll G,S;
    scanf("%lld %lld",&G,&S);
    while(m--){
        int u,v;
        ll g,s;
        scanf("%d %d %lld %lld",&u,&v,&g,&s);
        if(u==v)
            continue;
        add_edge(u,v,g,s,g*G+s*S);
        add_edge(v,u,g,s,g*G+s*S);
    }
    work();
    if(sum==n)
        printf("%lld\n",g_num*G+s_num*S);
    else
        puts("-1");
}


#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
#include<set>
#include<cmath>
#include<string>
#include<map>
#include<vector>
#include<ctime>
#include<stack>
using namespace std;
#define mm(a,b) memset(a,b,sizeof(a))
typedef long long ll;
typedef unsigned long long ull;
const long long mod = 1e9 + 7;
const int maxn = 5e4+100;
const ll inf = 0x3f3f3f3f3f3f3f3f;
int n,m,G,S;
struct node{
    int u;
    int v;
    ll g,s;
};
node st[maxn],road[maxn];
int vis[maxn];
ll ans=0,cnt=0;
bool cmp(node a,node b){
    if(a.g==b.g)
        return a.s<b.s;
    return a.g<b.g;
}
bool cmp1(node a,node b){
    return a.s<b.s;
}
int find(int x){
    if(vis[x]!=x)
        return vis[x]=find(vis[x]);
    return vis[x];
}
void kruskal(){
    int tmp=1;
    ans=inf;
    for(int i=1;i<=m;i++){
        for(int j=1;j<=n;j++)
            vis[j]=j;
        st[tmp++]=road[i];
        ll maxx=0;
        int t=1;
        sort(st,st+tmp,cmp1);
        for(int j=1;j<tmp;j++){
            int u=find(st[j].u);
            int v=find(st[j].v);
            if(u!=v){
                maxx=max(maxx,st[j].s);
                st[t++]=road[j];
                vis[u]=v;
            }
            if(t==n) break;
        }
        if(t==n)
            ans=min(ans,road[i].g*G+maxx*S);
        tmp=t;
    }
}
int main()
{
    scanf("%d %d",&n,&m);
    scanf("%d %d",&G,&S);
    for(int i=1;i<=m;i++){
        scanf("%d %d %lld %lld",&road[i].u,&road[i].v,&road[i].g,&road[i].s);
    }
    sort(road+1,road+1+m,cmp);
    kruskal();
    if(ans!=inf)
        printf("%lld\n",ans);
    else
        puts("-1");
}


#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
#include<set>
#include<cmath>
#include<string>
#include<map>
#include<vector>
#include<ctime>
#include<stack>
using namespace std;
#define mm(a,b) memset(a,b,sizeof(a))
typedef long long ll;
typedef unsigned long long ull;
const long long mod = 1e9 + 7;
const int maxn = 5e4+100;
const ll inf = 0x3f3f3f3f3f3f3f3f;
int n,m,G,S;
struct node{
    int u;
    int v;
    ll g,s;
};
node st[maxn],road[maxn];
int vis[maxn];
ll ans=0,cnt=0;
bool cmp(node a,node b){
    if(a.g==b.g)
        return a.s<b.s;
    return a.g<b.g;
}
bool cmp1(node a,node b){
    return a.s<b.s;
}
int find(int x){
    if(vis[x]!=x)
        return vis[x]=find(vis[x]);
    return vis[x];
}
void kruskal(){
    int tmp=1;
    ans=inf;
    for(int i=1;i<=m;i++){
        for(int j=1;j<=n;j++)
            vis[j]=j;
        st[tmp++]=road[i];
        ll maxx=0;
        int t=1;
        sort(st+1,st+tmp+1,cmp1);
        for(int j=1;j<tmp;j++){
            int u=find(st[j].u);
            int v=find(st[j].v);
            if(u!=v){
                maxx=max(maxx,st[j].s);
                st[t++]=road[j];
                vis[u]=v;
            }
            if(t==n) break;
        }
        if(t==n)
            ans=min(ans,road[i].g*G+maxx*S);
        tmp=t;
    }
}
int main()
{
    scanf("%d %d",&n,&m);
    scanf("%d %d",&G,&S);
    for(int i=1;i<=m;i++){
        scanf("%d %d %lld %lld",&road[i].u,&road[i].v,&road[i].g,&road[i].s);
    }
    sort(road+1,road+1+m,cmp);
    kruskal();
    if(ans!=inf)
        printf("%lld\n",ans);
    else
        puts("-1");
}


#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
#include<set>
#include<cmath>
#include<string>
#include<map>
#include<vector>
#include<ctime>
#include<stack>
using namespace std;
#define mm(a,b) memset(a,b,sizeof(a))
typedef long long ll;
typedef unsigned long long ull;
const long long mod = 1e9 + 7;
const int maxn = 5e4+100;
const int inf = 0x3f3f3f3f;
int n;
struct node{
    int next;
    int v;
    ll g,s;
    ll cost;
    friend bool operator < (node a,node b){
        return a.cost>b.cost;
    }
}road[maxn];
int head[300],cnt=0;
int vis[300];
void add_edge(int u,int v,ll g,ll s,ll cost){
    road[cnt].v=v;
    road[cnt].g=g;
    road[cnt].s=s;
    road[cnt].next=head[u];
    road[cnt].cost=cost;
    head[u]=cnt++;
}
ll ans=0,g_num=0,s_num=0;
int sum=1;
priority_queue<node> q;
void work(){
    while(!q.empty()){
        q.pop();
    }
    for(int i=head[1];i!=-1;i=road[i].next){
        q.push(road[i]);
    }
    vis[1]=1;
    while(!q.empty()&&sum!=n){
        node temp=q.top();
        q.pop();
        int v=temp.v;
        if(!vis[v]){
            g_num=max(g_num,temp.g);
            s_num=max(s_num,temp.s);
            vis[v]=1;
            sum++;
            for(int i=head[v];i!=-1;i=road[i].next){
                if(!vis[road[i].v]){
                    q.push(road[i]);
                }
            }

        }
    }
}
int main()
{
    mm(vis,0);
    mm(head,-1);
    cnt=0;
    sum=1;
    g_num=0,s_num=0,ans=0;
    int n,m;
    scanf("%d %d",&n,&m);
    ll G,S;
    scanf("%lld %lld",&G,&S);
    while(m--){
        int u,v;
        ll g,s;
        scanf("%d %d %lld %lld",&u,&v,&g,&s);
        if(u==v)
            continue;
        add_edge(u,v,g,s,g*G+s*S);
        add_edge(v,u,g,s,g*G+s*S);
    }
    work();
    printf("%lld\n",g_num*G+s_num*S);
}


#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
#include<set>
#include<cmath>
#include<string>
#include<map>
#include<vector>
#include<ctime>
#include<stack>
using namespace std;
#define mm(a,b) memset(a,b,sizeof(a))
typedef long long ll;
typedef unsigned long long ull;
const long long mod = 1e9 + 7;
const int maxn = 5e4+100;
const int inf = 0x3f3f3f3f;
int n;
int mini=inf;
struct node{
    int next;
    int v;
    ll number[2];
    ll cost;
    friend bool operator < (node a,node b){
        return a.cost>b.cost;
    }
}road[maxn];
int head[300],cnt=0;
int vis[300];
void add_edge(int u,int v,ll g,ll s,ll cost){
    road[cnt].v=v;
    road[cnt].number[0]=g;
    road[cnt].number[1]=s;
    road[cnt].next=head[u];
    road[cnt].cost=cost;
    head[u]=cnt++;
}
ll ans=0,g_num=0,s_num=0;
int sum;
priority_queue<node> q;
bool work(int u,ll g,ll s){
    mm(vis,0);
    vis[u]=1;
    sum=1;
    while(!q.empty()){
        q.pop();
    }
    for(int i=head[u];i!=-1;i=road[i].next){
        int v=road[i].v;
        if(!vis[v])
            q.push(road[i]);
    }
    while(!q.empty()&&sum<n){
        node tmp=q.top();
        q.pop();
        int v=tmp.v;
        if(!vis[v]&&tmp.number[0]<=g&&tmp.number[1]<=s){
            sum++;
            vis[v]=1;
            for(int i=head[v];i!=-1;i=road[i].next){
                int next=road[i].v;
                if(!vis[next])
                    q.push(road[i]);
            }
        }
    }
    if(sum==n)
        return true;
    return false;
}
int main()
{
    mm(head,-1);
    cnt=0;
    ans=0;
    int m;
    scanf("%d %d",&n,&m);
    ll G,S;
    int start=1;
    ll tmp=inf;
    scanf("%lld %lld",&G,&S);
    while(m--){
        int u,v;
        ll g,s;
        scanf("%d %d %lld %lld",&u,&v,&g,&s);
        if(u==v)
            continue;
        add_edge(u,v,g,s,g*G+s*S);
        add_edge(v,u,g,s,g*G+s*S);
    }
    ll lg=0,rg=1e9,ls=0,rs=1e9;
    int flag=0;
    while(lg<=rg){
        ll midg=(lg+rg)/2;
        flag=0;
        ls=0,rs=1e9;
        while(ls<=rs){
            ll mids=(ls+rs)/2;
            if(work(1,midg,mids)){
                ans=midg*G+mids*S;
                rs=mids-1;
                flag=1;
            }
            else{
                ls=mids+1;
            }
        }
        if(!flag){
            lg=midg+1;
        }
        else{
            rg=midg-1;
        }
    }
    if(ans)
        printf("%lld\n",ans);
    else
        puts("-1");
}


#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
#include<set>
#include<cmath>
#include<string>
#include<map>
#include<vector>
#include<ctime>
#include<stack>
using namespace std;
#define mm(a,b) memset(a,b,sizeof(a))
typedef long long ll;
typedef unsigned long long ull;
const long long mod = 1e9 + 7;
const int maxn = 5e4+100;
const int inf = 0x3f3f3f3f;
int n;
int mini=inf;
struct node{
    int next;
    int v;
    ll number[2];
    ll cost;
    friend bool operator < (node a,node b){
        return a.cost>b.cost;
    }
}road[maxn];
int head[300],cnt=0;
int vis[300];
void add_edge(int u,int v,ll g,ll s,ll cost){
    road[cnt].v=v;
    road[cnt].number[0]=g;
    road[cnt].number[1]=s;
    road[cnt].next=head[u];
    road[cnt].cost=cost;
    head[u]=cnt++;
}
ll ans=0,g_num=0,s_num=0;
int sum=1;
priority_queue<node> q;
bool work(int u,ll g,ll s){
    mm(vis,0);
    vis[u]=1;
    sum=1;
    for(int i=head[u];i!=-1;i=road[i].next){
        int v=road[i].v;
        if(!vis[v])
            q.push(road[i]);
    }
    while(!q.empty()&&sum<n){
        node tmp=q.top();
        q.pop();
        int v=tmp.v;
        if(!vis[v]&&tmp.number[0]<=g&&tmp.number[1]<=s){
            sum++;
            vis[v]=1;
            for(int i=head[v];i!=-1;i=road[i].next){
                int next=road[i].v;
                if(!vis[next])
                    q.push(road[i]);
            }
        }
    }
    if(sum==n)
        return true;
    return false;
}
int main()
{
    mm(head,-1);
    cnt=0;
    g_num=0,s_num=0,ans=0;
    int m;
    scanf("%d %d",&n,&m);
    ll G,S;
    int start=1;
    ll tmp=inf;
    scanf("%lld %lld",&G,&S);
    if(G>S)
        mini=0;
    else
        mini=1;
    while(m--){
        int u,v;
        ll g,s;
        scanf("%d %d %lld %lld",&u,&v,&g,&s);
        if(u==v)
            continue;
        add_edge(u,v,g,s,g*G+s*S);
        add_edge(v,u,g,s,g*G+s*S);
    }
    ll lg=0,rg=1e9,ls=0,rs=1e9;
    int flag=0;
    ll ans=0;
    while(lg<=rg){
        ll midg=(lg+rg)/2;
        flag=0;
        ls=0,rs=1e9;
        while(ls<=rs){
            ll mids=(ls+rs)/2;
            if(work(1,midg,mids)){
                ans=midg*G+mids*S;
                rs=mids-1;
                flag=1;
            }
            else{
                ls=mids+1;
            }
        }
        if(!flag){
            lg=midg+1;
        }
        else{
            rg=midg-1;
        }
    }
    if(ans)
        printf("%lld\n",ans);
    else
        puts("-1");
}


#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
#include<set>
#include<cmath>
#include<string>
#include<map>
#include<vector>
#include<ctime>
#include<stack>
using namespace std;
#define mm(a,b) memset(a,b,sizeof(a))
typedef long long ll;
typedef unsigned long long ull;
const long long mod = 1e9 + 7;
const int maxn = 5e4+100;
const int inf = 0x3f3f3f3f;
int n;
int mini=inf;
struct node{
    int next;
    int v;
    ll number[2];
    ll cost;
    friend bool operator < (node a,node b){
        return a.cost>b.cost;
    }
}road[maxn];
int head[300],cnt=0;
int vis[300];
void add_edge(int u,int v,ll g,ll s,ll cost){
    road[cnt].v=v;
    road[cnt].number[0]=g;
    road[cnt].number[1]=s;
    road[cnt].next=head[u];
    road[cnt].cost=cost;
    head[u]=cnt++;
}
ll ans=0,g_num=0,s_num=0;
int sum;
priority_queue<node> q;
bool work(int u,ll g,ll s){
    mm(vis,0);
    vis[u]=1;
    sum=1;
    while(!q.empty()){
        q.pop();
    }
    for(int i=head[u];i!=-1;i=road[i].next){
        int v=road[i].v;
        if(!vis[v])
            q.push(road[i]);
    }
    while(!q.empty()&&sum<n){
        node tmp=q.top();
        q.pop();
        int v=tmp.v;
        if(!vis[v]&&tmp.number[0]<=g&&tmp.number[1]<=s){
            sum++;
            vis[v]=1;
            for(int i=head[v];i!=-1;i=road[i].next){
                int next=road[i].v;
                if(!vis[next])
                    q.push(road[i]);
            }
        }
    }
    if(sum==n)
        return true;
    return false;
}
int main()
{
    mm(head,-1);
    cnt=0;
    ans=inf;
    int m;
    scanf("%d %d",&n,&m);
    ll G,S;
    int start=1;
    ll tmp=inf;
    scanf("%lld %lld",&G,&S);
    while(m--){
        int u,v;
        ll g,s;
        scanf("%d %d %lld %lld",&u,&v,&g,&s);
        if(u==v)
            continue;
        add_edge(u,v,g,s,g*G+s*S);
        add_edge(v,u,g,s,g*G+s*S);
    }
    ll lg=0,rg=1e9,ls=0,rs=1e9;
    int flag=0;
    while(lg<=rg){
        ll midg=(lg+rg)/2;
        flag=0;
        ls=0,rs=1e9;
        while(ls<=rs){
            ll mids=(ls+rs)/2;
            if(work(1,midg,mids)){
                ans=min(midg*G+mids*S,ans);
                rs=mids-1;
                flag=1;
            }
            else{
                ls=mids+1;
            }
        }
        if(!flag){
            lg=midg+1;
        }
        else{
            rg=midg-1;
        }
    }
    if(ans!=inf)
        printf("%lld\n",ans);
    else
        puts("-1");
}


#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
#include<set>
#include<cmath>
#include<string>
#include<map>
#include<vector>
#include<ctime>
#include<stack>
using namespace std;
#define mm(a,b) memset(a,b,sizeof(a))
typedef long long ll;
typedef unsigned long long ull;
const long long mod = 1e9 + 7;
const int maxn = 5e4+100;
const int inf = 0x3f3f3f3f;
int n;
int mini=inf;
struct node{
    int next;
    int v;
    ll number[2];
    ll cost;
    friend bool operator < (node a,node b){
        return a.cost>b.cost;
    }
}road[maxn];
int head[300],cnt=0;
int vis[300];
void add_edge(int u,int v,ll g,ll s,ll cost){
    road[cnt].v=v;
    road[cnt].number[0]=g;
    road[cnt].number[1]=s;
    road[cnt].next=head[u];
    road[cnt].cost=cost;
    head[u]=cnt++;
}
ll ans=0,g_num=0,s_num=0;
int sum;
priority_queue<node> q;
bool work(int u,ll g,ll s){
    mm(vis,0);
    vis[u]=1;
    sum=1;
    while(!q.empty()){
        q.pop();
    }
    for(int i=head[u];i!=-1;i=road[i].next){
        int v=road[i].v;
        if(!vis[v])
            q.push(road[i]);
    }
    while(!q.empty()&&sum<n){
        node tmp=q.top();
        q.pop();
        int v=tmp.v;
        if(!vis[v]&&tmp.number[0]<=g&&tmp.number[1]<=s){
            sum++;
            vis[v]=1;
            for(int i=head[v];i!=-1;i=road[i].next){
                int next=road[i].v;
                if(!vis[next])
                    q.push(road[i]);
            }
        }
    }
    if(sum==n)
        return true;
    return false;
}
int main()
{
    mm(head,-1);
    cnt=0;
    ans=0;
    int m;
    scanf("%d %d",&n,&m);
    ll G,S;
    int start=1;
    ll tmp=inf;
    scanf("%lld %lld",&G,&S);
    while(m--){
        int u,v;
        ll g,s;
        scanf("%d %d %lld %lld",&u,&v,&g,&s);
        if(u==v)
            continue;
        add_edge(u,v,g,s,g*G+s*S);
        add_edge(v,u,g,s,g*G+s*S);
    }
    ll lg=0,rg=1e9,ls=0,rs=1e9;
    int flag=0;
    while(lg<=rg){
        ll midg=(lg+rg)/2;
        flag=0;
        ls=0,rs=1e9;
        while(ls<=rs){
            ll mids=(ls+rs)/2;
            if(work(1,midg,mids)){
                ans=min(midg*G+mids*S,ans);
                rs=mids-1;
                flag=1;
            }
            else{
                ls=mids+1;
            }
        }
        if(!flag){
            lg=midg+1;
        }
        else{
            rg=midg-1;
        }
    }
    if(ans)
        printf("%lld\n",ans);
    else
        puts("-1");
}


#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll n, m, G, S, X;
multiset < ll > E;
vector<ll> v[209],l[209];
ll f[209];
bool dfs(ll a, ll b){
    f[a] = 1;
    if(a == b) return 1;
    bool F = 0;
    for(ll i= 0; i < v[a].size(); i++){
        if(f[v[a][i]]) continue;
        if(dfs(v[a][i],b)) {
            X = max(X, l[a][i]);
            F = 1;
        }
    }
    return F;
}
ll adddd(ll a , ll b, ll w){
    for(ll i = 1; i <= n; i++)
        f[i] = 0;
    X= 0;
    if(!dfs(a, b)){
        v[a].push_back(b);
        l[a].push_back(b);
        E.insert(w);
    }
    else{
        if(w < X){
            E.erase(E.find(X));
            v[a].push_back(b);
            l[a].push_back(b);
            E.insert(w);
        }
    }
    if(E.size() != n - 1) return -1;
    else return (*(--E.end()));
}
main(){
    cin >> n >> m >> G >> S;
    vector<pair<pair<ll,ll>,pair<ll,ll> > > v;
    for(ll i = 0; i < m; i++){
        ll a,b,g,s;
        cin >> a >> b >> g >> s;
        v.push_back({{g,s},{a,b}});
    }
    sort(v.begin(),v.end());
    ll ans = -1;
    for(ll i = 0; i < v.size(); i++){
        ll g = v[i].first.first, s = v[i].first.second, a = v[i].second.first, b = v[i].second.second;
        ll X = adddd(a,b,s);
        if(X != -1) {
            if (ans == -1) ans = G * g + S * X;
            else ans = min(ans, G * g + S * X);
        }
    }
    cout << ans << endl;
}


#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll n, m, G, S, X, A , B;
multiset < ll > E;
vector<ll> v[209],l[209];
ll f[209];
bool dfs(ll a, ll b){
    f[a] = 1;
    if(a == b) return 1;
    bool F = 0;
    for(ll i= 0; i < v[a].size(); i++){
        if(f[v[a][i]]) continue;
        if(dfs(v[a][i],b)) {
            if(X < l[a][i]){
                X = max(X, l[a][i]);
                A = l[a][i];
                B = a;
            }
            F = 1;
        }
    }
    return F;
}
ll adddd(ll a , ll b, ll w){
    for(ll i = 1; i <= n; i++)
        f[i] = 0;
    X= 0;
    if(!dfs(a, b)){

        v[a].push_back(b);
        l[a].push_back(w);
        E.insert(w);
    }
    else{
        if(w < X){
            E.erase(E.find(X));
            for(ll i = 0; i < v[A].size(); i++){
                if(v[A][i] == B){
                    swap(v[A][i], v[A].back());
                    swap(l[A][i], l[A].back());
                    v[A].pop_back();
                    break;
                }
            }
            for(ll i = 0; i < v[B].size(); i++){
                if(v[B][i] == A){
                    swap(v[B][i], v[B].back());
                    swap(l[B][i], l[B].back());
                    v[B].pop_back();
                    break;
                }
            }
            v[a].push_back(b);
            v[b].push_back(a);
            l[b].push_back(w);
            l[a].push_back(w);
            E.insert(w);
        }
    }
    if(E.size() != n - 1) return -1;
    else return (*(--E.end()));
}
main(){
    cin >> n >> m >> G >> S;
    vector<pair<pair<ll,ll>,pair<ll,ll> > > v;
    for(ll i = 0; i < m; i++){
        ll a,b,g,s;
        cin >> a >> b >> g >> s;
        v.push_back({{g,s},{a,b}});
    }
    sort(v.begin(),v.end());
    ll ans = -1;
    for(ll i = 0; i < v.size(); i++){
        ll g = v[i].first.first, s = v[i].first.second, a = v[i].second.first, b = v[i].second.second;
        ll X = adddd(a,b,s);
        if(X != -1) {
            if (ans == -1) ans = G * g + S * X;
            else ans = min(ans, G * g + S * X);
        }
    }
    cout << ans << endl;
}


#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll n, m, G, S, X, A , B;
multiset < ll > E;
vector<ll> v[209],l[209];
ll f[209];
bool dfs(ll a, ll b){
    f[a] = 1;
    if(a == b) return 1;
    bool F = 0;
    for(ll i= 0; i < v[a].size(); i++){
        if(f[v[a][i]]) continue;
        if(dfs(v[a][i],b)) {
            if(X < l[a][i]){
                X = max(X, l[a][i]);
                A = v[a][i];
                B = a;
            }
            F = 1;
        }
    }
    return F;
}
ll adddd(ll a , ll b, ll w){
    for(ll i = 1; i <= n; i++)
        f[i] = 0;
    X= 0;
    if(!dfs(a, b)){

        v[a].push_back(b);
        v[b].push_back(a);
        l[b].push_back(w);
        l[a].push_back(w);
        E.insert(w);
    }
    else{
        if(w < X){
            E.erase(E.find(X));
            for(ll i = 0; i < v[A].size(); i++){
                if(v[A][i] == B){
                    swap(v[A][i], v[A].back());
                    swap(l[A][i], l[A].back());
                    v[A].pop_back();
                    l[A].pop_back();
                    break;
                }
            }
            for(ll i = 0; i < v[B].size(); i++){
                if(v[B][i] == A){
                    swap(v[B][i], v[B].back());
                    swap(l[B][i], l[B].back());
                    v[B].pop_back();
                    l[B].pop_back();
                    break;
                }
            }
            v[a].push_back(b);
            v[b].push_back(a);
            l[b].push_back(w);
            l[a].push_back(w);
            E.insert(w);
        }
    }
    if(E.size() != n - 1) return -1;
    else return (*(--E.end()));
}
main(){
    cin >> n >> m >> G >> S;
    vector<pair<pair<ll,ll>,pair<ll,ll> > > v;
    for(ll i = 0; i < m; i++){
        ll a,b,g,s;
        cin >> a >> b >> g >> s;
        v.push_back({{g,s},{a,b}});
    }
    sort(v.begin(),v.end());
    ll ans = -1;
    for(ll i = 0; i < v.size(); i++){
        ll g = v[i].first.first, s = v[i].first.second, a = v[i].second.first, b = v[i].second.second;
        ll X = adddd(a,b,s);
        if(X != -1) {
            if (ans == -1) ans = G * g + S * X;
            else ans = min(ans, G * g + S * X);
        }
    }
    cout << ans << endl;
}


#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll n, m, G, S, X, A , B;
multiset < ll > E;
vector<ll> v[209],l[209];
ll f[209];
bool dfs(ll a, ll b){
    f[a] = 1;
    if(a == b) return 1;
    bool F = 0;
    for(ll i= 0; i < v[a].size(); i++){
        if(f[v[a][i]]) continue;
        if(dfs(v[a][i],b)) {
            if(X < l[a][i]){
                X = max(X, l[a][i]);
                A = l[a][i];
                B = a;
            }
            F = 1;
        }
    }
    return F;
}
ll adddd(ll a , ll b, ll w){
    for(ll i = 1; i <= n; i++)
        f[i] = 0;
    X= 0;
    if(!dfs(a, b)){

        v[a].push_back(b);
        l[a].push_back(w);
        E.insert(w);
    }
    else{
        if(w < X){
            E.erase(E.find(X));
            for(ll i = 0; i < v[A].size(); i++){
                if(v[A][i] == B){
                    swap(v[A][i], v[A].back());
                    swap(l[A][i], l[A].back());
                    v[A].pop_back();

                    l[A].pop_back();
                    break;
                }
            }
            for(ll i = 0; i < v[B].size(); i++){
                if(v[B][i] == A){
                    swap(v[B][i], v[B].back());
                    swap(l[B][i], l[B].back());
                    v[B].pop_back();
                    l[B].pop_back();
                    break;
                }
            }
            v[a].push_back(b);
            v[b].push_back(a);
            l[b].push_back(w);
            l[a].push_back(w);
            E.insert(w);
        }
    }
    if(E.size() != n - 1) return -1;
    else return (*(--E.end()));
}
main(){
    cin >> n >> m >> G >> S;
    vector<pair<pair<ll,ll>,pair<ll,ll> > > v;
    for(ll i = 0; i < m; i++){
        ll a,b,g,s;
        cin >> a >> b >> g >> s;
        v.push_back({{g,s},{a,b}});
    }
    sort(v.begin(),v.end());
    ll ans = -1;
    for(ll i = 0; i < v.size(); i++){
        ll g = v[i].first.first, s = v[i].first.second, a = v[i].second.first, b = v[i].second.second;
        ll X = adddd(a,b,s);
        if(X != -1) {
            if (ans == -1) ans = G * g + S * X;
            else ans = min(ans, G * g + S * X);
        }
    }
    cout << ans << endl;
}


#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll n, m, G, S, X, A , B;
multiset < ll > E;
vector<ll> v[209],l[209];
ll f[209];
bool dfs(ll a, ll b){
    f[a] = 1;
    if(a == b) return 1;
    bool F = 0;
    for(ll i= 0; i < v[a].size(); i++){
        if(f[v[a][i]]) continue;
        if(dfs(v[a][i],b)) {
            if(X < l[a][i]){
                X = max(X, l[a][i]);
                A = l[a][i];
                B = a;
            }
            F = 1;
        }
    }
    return F;
}
ll adddd(ll a , ll b, ll w){
    for(ll i = 1; i <= n; i++)
        f[i] = 0;
    X= 0;
    if(!dfs(a, b)){

        v[a].push_back(b);
        v[b].push_back(a);
        l[b].push_back(w);
        l[a].push_back(w);
        E.insert(w);
    }
    else{
        if(w < X){
        //    E.erase(E.find(X));
            for(ll i = 0; i < v[A].size(); i++){
                if(v[A][i] == B){
                    swap(v[A][i], v[A].back());
                    swap(l[A][i], l[A].back());
                    v[A].pop_back();
                    l[A].pop_back();
                    break;
                }
            }
            for(ll i = 0; i < v[B].size(); i++){
                if(v[B][i] == A){
                    swap(v[B][i], v[B].back());
                    swap(l[B][i], l[B].back());
                    v[B].pop_back();
                    l[B].pop_back();
                    break;
                }
            }
            v[a].push_back(b);
            v[b].push_back(a);
            l[b].push_back(w);
            l[a].push_back(w);
            E.insert(w);
        }
    }
    if(E.size() != n - 1) return -1;
    else return (*(--E.end()));
}
main(){
    cin >> n >> m >> G >> S;
    vector<pair<pair<ll,ll>,pair<ll,ll> > > v;
    for(ll i = 0; i < m; i++){
        ll a,b,g,s;
        cin >> a >> b >> g >> s;
        v.push_back({{g,s},{a,b}});
    }
    sort(v.begin(),v.end());
    ll ans = -1;
    for(ll i = 0; i < v.size(); i++){
        ll g = v[i].first.first, s = v[i].first.second, a = v[i].second.first, b = v[i].second.second;
        ll X = adddd(a,b,s);
        if(X != -1) {
            if (ans == -1) ans = G * g + S * X;
            else ans = min(ans, G * g + S * X);
        }
    }
    cout << ans << endl;
}


#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll n, m, G, S, X, A , B;
multiset < ll > E;
vector<ll> v[209],l[209];
ll f[209];
bool dfs(ll a, ll b){
    f[a] = 1;
    if(a == b) return 1;
    bool F = 0;
    for(ll i= 0; i < v[a].size(); i++){
        if(f[v[a][i]]) continue;
        if(dfs(v[a][i],b)) {
            if(X < l[a][i]){
                X = max(X, l[a][i]);
                A = l[a][i];
                B = a;
            }
            F = 1;
        }
    }
    return F;
}
ll adddd(ll a , ll b, ll w){
    for(ll i = 1; i <= n; i++)
        f[i] = 0;
    X= 0;
    if(!dfs(a, b)){

        v[a].push_back(b);
        v[b].push_back(a);
        l[b].push_back(w);
        l[a].push_back(w);
        E.insert(w);
    }
    else{
        if(w < X){
            E.erase(E.find(X));
            for(ll i = 0; i < v[A].size(); i++){
                if(v[A][i] == B){
                    swap(v[A][i], v[A].back());
                    swap(l[A][i], l[A].back());
                    v[A].pop_back();
                    l[A].pop_back();
                    break;
                }
            }
            for(ll i = 0; i < v[B].size(); i++){
                if(v[B][i] == A){
                    swap(v[B][i], v[B].back());
                    swap(l[B][i], l[B].back());
                    v[B].pop_back();
                    l[B].pop_back();
                    break;
                }
            }
            v[a].push_back(b);
            v[b].push_back(a);
            l[b].push_back(w);
            l[a].push_back(w);
            E.insert(w);
        }
    }
    if(E.size() != n - 1) return -1;
    else return (*(--E.end()));
}
main(){
    cin >> n >> m >> G >> S;
    vector<pair<pair<ll,ll>,pair<ll,ll> > > v;
    for(ll i = 0; i < m; i++){
        ll a,b,g,s;
        cin >> a >> b >> g >> s;
        v.push_back({{g,s},{a,b}});
    }
    sort(v.begin(),v.end());
    ll ans = -1;
    for(ll i = 0; i < v.size(); i++){
        ll g = v[i].first.first, s = v[i].first.second, a = v[i].second.first, b = v[i].second.second;
        ll X = adddd(a,b,s);
        if(X != -1) {
            if (ans == -1) ans = G * g + S * X;
            else ans = min(ans, G * g + S * X);
        }
    }
    cout << ans << endl;
}


#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
using namespace std;
#define Foreach(i, c) for(__typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)
#define For(i,a,b) for(int (i)=(a);(i) < (b); ++(i))
#define rof(i,a,b) for(int (i)=(a);(i) > (b); --(i))
#define rep(i, c)	for(auto &(i) : (c))
#define x     first
#define y     second
#define pb  push_back
#define PB  pop_back()
#define iosfal  ios_base::sync_with_stdio(false)
#define mp(a,b) make_pair(a,b)
#define sqr(a)  ((a)*(a))
#define all(a)  a.begin() , a.end()
#define error(x) cerr << #x << " = " << (x) <<endl
#define Error(a,b) cerr<<"( "<<#a<<" , "<<#b<<" ) = ( "<<(a)<<" , "<<(b)<<" )\n";
#define errop(a) cerr<<#a<<" = ( "<<((a).x)<<" , "<<((a).y)<<" )\n";
#define coud(a,b) cout<<fixed << setprecision((b)) << (a) << endl
#define dis(a,b)	(point(a.x - b.x, a.y - b.y))
#define L(x)	((x)<<1)
#define R(x)	(((x)<<1)+1)
#define mt	make_tuple
#define get(a,b)	get<b>(a)
typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update>	os;
typedef pair<int,int>pii;
typedef long long ll;
typedef pair<pii,int> piii;
const int maxn = 210, maxm = 5e4 + 10;
const ll inf = 1LL << 62;
int n,m;
struct node{
	int par[maxn];
	int moal;
	inline void init(){
		moal = 1;
		fill(par,par+maxn,-1);
	}
	node(){moal = ::n;init();}
	inline int root(int &v){
		return par[v] < 0 ? v : (par[v] = root(par[v]));
	}
	inline void merge(int x,int y){
		x = root(x), y = root(y);
		if(x == y)	return ;
		if(par[y] < par[x])
			swap(x,y);
		par[x] += par[y];
		par[y] = x;
		moal ++ ;
	}
	inline node operator * (node n){
		node a = *this;
		For(i,0,::n)
			a.merge(i,n.root(i));
		return a;
	}
	inline bool con(){
		return moal == n;
	}
}seg[maxm * 4], emp;
int s[maxm], g[maxm];
int V[maxm],U[maxm];
int G,S;
node ANS;
int ans;
inline void upd(int p,int i,int id = 1,int l = 0,int r = m){
	seg[id].merge(V[i],U[i]);
	if(r-l < 2)	return ;
	int mid = (l+r)/2;
	if(p < mid)
		upd(p,i,L(id),l,mid);
	else
		upd(p,i,R(id),mid,r);
}
inline void ask(int id = 1,int l = 0,int r = m){
	int mid = (l+r)/2;
	if(ANS.con())	return ;
	if(r-l<2){
		ans = max(ans,r-1);
		ANS = ANS * seg[id];
		return ;
	}
	if(!(ANS * seg[L(id)]).con()){
		ans = max(ans,mid-1);
		ANS = ANS * seg[L(id)];
		ask(R(id),mid,r);
	}
	else
		ask(L(id),l,mid);
}
vector<int> ps,pg;
inline int ms(){
	if(!seg[1].con())	return -1;
	ans = 0;
	ANS = emp;
	ask();
	return s[ps[ans]];
}
int sp[maxm];
int main(){
	iosfal;
	cin >> n >> m >> G >> S;
	ll ans = inf;
	For(i,0,m){
		cin >> V[i] >> U[i] >> g[i] >> s[i];
		-- V[i];
		-- U[i];
		ps.pb(i);
		pg.pb(i);
	}
	sort(all(ps), [](const int &i,const int &j){return s[i] < s[j];});
	sort(all(pg), [](const int &i,const int &j){return g[i] < g[j];});
	if(n == 1){
		cout << 0 << endl;
		return 0;
	}
	For(i,0,ps.size())
		sp[ps[i]] = i;
	rep(i,pg){
		upd(sp[i],i);
		int x = ms();
		if(x + 1)
			ans = min(ans,1LL * G * g[i] + 1LL * x * S);
	}
	if(ans == inf)
		cout << -1 << endl;
	else
		cout << ans << endl;
}