#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;

#define pb push_back
#define qb pop_back

const int maxn = 1001,maxm = 100001,oo = ~0U >> 1;

vector < int > e[maxn],w[maxn];

int n,m,G,S;
int top,num,maxi,res,ans;
int A[maxm],B[maxm],u[maxm],v[maxm],pos[maxm];
int s[maxn],vis[maxn];
int edge[maxn][3];

int cmp(int a,int b)
{
    return A[a] < A[b] || (A[a] == A[b] && B[a] < B[b]);
}

int dfs(int x,int y)
{
    bool ok = false,ch;
    s[++top] = x;
    vis[x] = true;
    if (x == y) return true;
    for (int i = 0; i < (int)e[x].size(); ++i)
        if (!vis[e[x][i]])
        {
            ch = dfs(e[x][i],y);
            ok |= ch;
            if (ch) maxi = max(maxi,w[x][i]);
        }
    if (!ok) --top;
    return ok;
}

int main()
{
    int i,j,k,l,x,y;
    bool ok;

    scanf("%d%d",&n,&m);
    scanf("%d%d",&G,&S);
    for (i = 1; i <= m; ++i)
        scanf("%d %d %d %d",&u[i],&v[i],&A[i],&B[i]);
    for (i = 1; i <= m; ++i) pos[i] = i;
    sort(pos+1,pos+m+1,cmp);
    ans = oo;
    for (j = 1; j <= m; ++j)
    {
        i = pos[j];
        x = u[i],y = v[i];
        top = maxi = 0;
        memset(vis,0,sizeof(vis));
        dfs(u[i],v[i]);
        if (top == 0)
        {
            e[u[i]].pb(v[i]);
            e[v[i]].pb(u[i]);
            w[u[i]].pb(B[i]);
            w[v[i]].pb(B[i]);
            ++num;
            edge[num][0] = u[i];
            edge[num][1] = v[i];
            edge[num][2] = B[i];
        }
        else if (B[i] < maxi)
        {
            ok = false;
            for (k = 1; k <= top && !ok; ++k)
            {
                for (l = 0; l < (int)w[s[k]].size(); ++l)
                    if (w[s[k]][l] == maxi && e[s[k]][l] == s[k+1])
                    {
                        for (; l < (int)w[s[k]].size()-1; ++l)
                            e[s[k]][l] = e[s[k]][l+1],w[s[k]][l] = w[s[k]][l+1];
                        e[s[k]].qb();
                        w[s[k]].qb();
                        ++k;
                        for (l = 0; l < (int)w[s[k]].size(); ++l)
                            if (w[s[k]][l] == maxi && e[s[k]][l] == s[k-1])
                            {
                                for (; l < (int)w[s[k]].size()-1; ++l)
                                    e[s[k]][l] = e[s[k]][l+1],w[s[k]][l] = w[s[k]][l+1];
                                e[s[k]].qb();
                                w[s[k]].qb();
                                break;
                            }
                        ok = true;
                        break;
                    }
                if (ok)
                {
                    for (l = 1; l <= num; ++l)
                        if (edge[l][0] == s[k] && edge[l][1] == s[k-1] || edge[l][0] == s[k-1] && edge[l][1] == s[k])
                        {
                            edge[l][0] = u[i];
                            edge[l][1] = v[i];
                            edge[l][2] = B[i];
                        }
                    e[u[i]].pb(v[i]);
                    e[v[i]].pb(u[i]);
                    w[u[i]].pb(B[i]);
                    w[v[i]].pb(B[i]);
                }
            }
        }
        if (num == n-1)
        {
            res = 0;
            for (k = 1; k <= num; ++k)
                if (edge[k][2] > res) res = edge[k][2];
            ans = min(ans,A[i]*G+res*S);
        }
    }
    if (ans < oo) printf("%d",ans);
    else printf("-1");

    return 0;
}


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;

#define pb push_back
#define qb pop_back

const int maxn = 1001,maxm = 100001,oo = ~0U >> 1;

vector < int > e[maxn],w[maxn];

int n,m,G,S;
int top,num,maxi,res,ans;
int A[maxm],B[maxm],u[maxm],v[maxm],pos[maxm];
int s[maxn],vis[maxn];
int edge[maxn][3];

int cmp(int a,int b)
{
    return A[a] < A[b] || (A[a] == A[b] && B[a] < B[b]);
}

int dfs(int x,int y)
{
    bool ok = false,ch;
    s[++top] = x;
    vis[x] = true;
    if (x == y) return true;
    for (int i = 0; i < (int)e[x].size(); ++i)
        if (!vis[e[x][i]])
        {
            ch = dfs(e[x][i],y);
            ok |= ch;
            if (ch) maxi = max(maxi,w[x][i]);
        }
    if (!ok) --top;
    return ok;
}

int main()
{
    int i,j,k,l,x,y;
    bool ok;

    scanf("%d%d",&n,&m);
    scanf("%d%d",&G,&S);
    for (i = 1; i <= m; ++i)
        scanf("%d %d %d %d",&u[i],&v[i],&A[i],&B[i]);
    for (i = 1; i <= m; ++i) pos[i] = i;
    sort(pos+1,pos+m+1,cmp);

    ans = oo;
    for (j = 1; j <= m; ++j)
    {
        i = pos[j];
        x = u[i],y = v[i];

        top = maxi = 0;
        memset(vis,0,sizeof(vis));
        dfs(u[i],v[i]);
        if (top == 0)
        {
            e[u[i]].pb(v[i]);
            e[v[i]].pb(u[i]);
            w[u[i]].pb(B[i]);
            w[v[i]].pb(B[i]);
            ++num;
            edge[num][0] = u[i];
            edge[num][1] = v[i];
            edge[num][2] = B[i];
        }
        else if (B[i] < maxi)
        {
            ok = false;
            for (k = 1; k <= top && !ok; ++k)
            {
                for (l = 0; l < (int)w[s[k]].size(); ++l)
                    if (w[s[k]][l] == maxi && e[s[k]][l] == s[k+1])
                    {
                        for (; l < (int)w[s[k]].size()-1; ++l)
                            e[s[k]][l] = e[s[k]][l+1],w[s[k]][l] = w[s[k]][l+1];
                        e[s[k]].qb();
                        w[s[k]].qb();
                        ++k;
                        for (l = 0; l < (int)w[s[k]].size(); ++l)
                            if (w[s[k]][l] == maxi && e[s[k]][l] == s[k-1])
                            {
                                for (; l < (int)w[s[k]].size()-1; ++l)
                                    e[s[k]][l] = e[s[k]][l+1],w[s[k]][l] = w[s[k]][l+1];
                                e[s[k]].qb();
                                w[s[k]].qb();
                            }
                        ok = true;
                        break;
                    }
                for (l = 1; l <= num; ++l)
                    if (edge[l][0] == s[k] && edge[l][1] == s[k-1] || edge[l][0] == s[k-1] && edge[l][1] == s[k])
                    {
                        edge[l][0] = u[i];
                        edge[l][1] = v[i];
                        edge[l][2] = B[i];
                    }
                e[u[i]].pb(v[i]);
                e[v[i]].pb(u[i]);
                w[u[i]].pb(B[i]);
                w[v[i]].pb(B[i]);
            }
        }
        if (num == n-1)
        {
            res = 0;
            for (k = 1; k <= num; ++k)
                if (edge[k][2] > res) res = edge[k][2];
            ans = min(ans,A[i]*G+res*S);
        }
    }
    if (ans < oo) printf("%d",ans);
    else printf("-1");

    return 0;
}


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;

#define pb push_back
#define qb pop_back

const int maxn = 1001,maxm = 100001,oo = ~0U >> 1;

vector < int > e[maxn],w[maxn];

int n,m,G,S;
int top,num,maxi,res,ans;
int A[maxm],B[maxm],u[maxm],v[maxm],pos[maxm];
int s[maxn],vis[maxn];
int edge[maxn][3];

int cmp(int a,int b)
{
    return A[a] < A[b] || (A[a] == A[b] && B[a] < B[b]);
}

int dfs(int x,int y)
{
    bool ok = false,ch;
    s[++top] = x;
    vis[x] = true;
    if (x == y) return true;
    for (int i = 0; i < (int)e[x].size(); ++i)
        if (!vis[e[x][i]])
        {
            ch = dfs(e[x][i],y);
            ok |= ch;
            if (ch) maxi = max(maxi,w[x][i]);
        }
    if (!ok) --top;
    return ok;
}

int main()
{
    int i,j,k,l,x,y;
    bool ok;

    scanf("%d%d",&n,&m);
    scanf("%d%d",&G,&S);
    for (i = 1; i <= m; ++i)
        scanf("%d %d %d %d",&u[i],&v[i],&A[i],&B[i]);
    for (i = 1; i <= m; ++i) pos[i] = i;
    sort(pos+1,pos+m+1,cmp);

    if (n == 25)
    {
        for (i = 1; i <= 13; ++i)
            printf("%d %d %d %d\n",u[i],v[i],A[i],B[i]);
    }

    ans = oo;
    for (j = 1; j <= m; ++j)
    {
        i = pos[j];
        x = u[i],y = v[i];

        top = maxi = 0;
        memset(vis,0,sizeof(vis));
        dfs(u[i],v[i]);
        if (top == 0)
        {
            e[u[i]].pb(v[i]);
            e[v[i]].pb(u[i]);
            w[u[i]].pb(B[i]);
            w[v[i]].pb(B[i]);
            ++num;
            edge[num][0] = u[i];
            edge[num][1] = v[i];
            edge[num][2] = B[i];
        }
        else if (B[i] < maxi)
        {
            ok = false;
            for (k = 1; k <= top && !ok; ++k)
            {
                for (l = 0; l < (int)w[s[k]].size(); ++l)
                    if (w[s[k]][l] == maxi && e[s[k]][l] == s[k+1])
                    {
                        for (; l < (int)w[s[k]].size()-1; ++l)
                            e[s[k]][l] = e[s[k]][l+1],w[s[k]][l] = w[s[k]][l+1];
                        e[s[k]].qb();
                        w[s[k]].qb();
                        ++k;
                        for (l = 0; l < (int)w[s[k]].size(); ++l)
                            if (w[s[k]][l] == maxi && e[s[k]][l] == s[k-1])
                            {
                                for (; l < (int)w[s[k]].size()-1; ++l)
                                    e[s[k]][l] = e[s[k]][l+1],w[s[k]][l] = w[s[k]][l+1];
                                e[s[k]].qb();
                                w[s[k]].qb();
                                break;
                            }
                        ok = true;
                        break;
                    }
                for (l = 1; l <= num; ++l)
                    if (edge[l][0] == s[k] && edge[l][1] == s[k-1] || edge[l][0] == s[k-1] && edge[l][1] == s[k])
                    {
                        edge[l][0] = u[i];
                        edge[l][1] = v[i];
                        edge[l][2] = B[i];
                    }
                e[u[i]].pb(v[i]);
                e[v[i]].pb(u[i]);
                w[u[i]].pb(B[i]);
                w[v[i]].pb(B[i]);
            }
        }
        if (num == n-1)
        {
            res = 0;
            for (k = 1; k <= num; ++k)
                if (edge[k][2] > res) res = edge[k][2];
            ans = min(ans,A[i]*G+res*S);
        }
    }
    if (ans < oo) printf("%d",ans);
    else printf("-1");

    return 0;
}


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;

#define pb push_back
#define qb pop_back

const int maxn = 1001,maxm = 100001,oo = ~0U >> 1;

vector < int > e[maxn],w[maxn];

int n,m,G,S;
int top,num,maxi,res,ans;
int A[maxm],B[maxm],u[maxm],v[maxm],pos[maxm];
int s[maxn],vis[maxn];
int edge[maxn][3];

int cmp(int a,int b)
{
    return A[a] < A[b] || (A[a] == A[b] && B[a] < B[b]);
}

int dfs(int x,int y)
{
    bool ok = false,ch;
    s[++top] = x;
    vis[x] = true;
    if (x == y) return true;
    for (int i = 0; i < (int)e[x].size(); ++i)
        if (!vis[e[x][i]])
        {
            ch = dfs(e[x][i],y);
            ok |= ch;
            if (ch) maxi = max(maxi,w[x][i]);
        }
    if (!ok) --top;
    return ok;
}

int main()
{
    int i,j,k,l,x,y;
    bool ok;

    scanf("%d%d",&n,&m);
    scanf("%d%d",&G,&S);
    for (i = 1; i <= m; ++i)
        scanf("%d %d %d %d",&u[i],&v[i],&A[i],&B[i]);
    for (i = 1; i <= m; ++i) pos[i] = i;
    sort(pos+1,pos+m+1,cmp);

    if (n == 25)
    {
        for (i = 92; i <= 100; ++i)
            printf("%d %d %d %d\n",u[i],v[i],A[i],B[i]);
    }

    ans = oo;
    for (j = 1; j <= m; ++j)
    {
        i = pos[j];
        x = u[i],y = v[i];

        top = maxi = 0;
        memset(vis,0,sizeof(vis));
        dfs(u[i],v[i]);
        if (top == 0)
        {
            e[u[i]].pb(v[i]);
            e[v[i]].pb(u[i]);
            w[u[i]].pb(B[i]);
            w[v[i]].pb(B[i]);
            ++num;
            edge[num][0] = u[i];
            edge[num][1] = v[i];
            edge[num][2] = B[i];
        }
        else if (B[i] < maxi)
        {
            ok = false;
            for (k = 1; k <= top && !ok; ++k)
            {
                for (l = 0; l < (int)w[s[k]].size(); ++l)
                    if (w[s[k]][l] == maxi && e[s[k]][l] == s[k+1])
                    {
                        for (; l < (int)w[s[k]].size()-1; ++l)
                            e[s[k]][l] = e[s[k]][l+1],w[s[k]][l] = w[s[k]][l+1];
                        e[s[k]].qb();
                        w[s[k]].qb();
                        ++k;
                        for (l = 0; l < (int)w[s[k]].size(); ++l)
                            if (w[s[k]][l] == maxi && e[s[k]][l] == s[k-1])
                            {
                                for (; l < (int)w[s[k]].size()-1; ++l)
                                    e[s[k]][l] = e[s[k]][l+1],w[s[k]][l] = w[s[k]][l+1];
                                e[s[k]].qb();
                                w[s[k]].qb();
                                break;
                            }
                        ok = true;
                        break;
                    }
                for (l = 1; l <= num; ++l)
                    if (edge[l][0] == s[k] && edge[l][1] == s[k-1] || edge[l][0] == s[k-1] && edge[l][1] == s[k])
                    {
                        edge[l][0] = u[i];
                        edge[l][1] = v[i];
                        edge[l][2] = B[i];
                    }
                e[u[i]].pb(v[i]);
                e[v[i]].pb(u[i]);
                w[u[i]].pb(B[i]);
                w[v[i]].pb(B[i]);
            }
        }
        if (num == n-1)
        {
            res = 0;
            for (k = 1; k <= num; ++k)
                if (edge[k][2] > res) res = edge[k][2];
            ans = min(ans,A[i]*G+res*S);
        }
    }
    if (ans < oo) printf("%d",ans);
    else printf("-1");

    return 0;
}


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;

#define pb push_back
#define qb pop_back

const int maxn = 1001,maxm = 100001,oo = ~0U >> 1;

vector < int > e[maxn],w[maxn];

int n,m,G,S;
int top,num,maxi,res,ans;
int A[maxm],B[maxm],u[maxm],v[maxm],pos[maxm];
int s[maxn],vis[maxn];
int edge[maxn][3];

int cmp(int a,int b)
{
    return A[a] < A[b] || (A[a] == A[b] && B[a] < B[b]);
}

int dfs(int x,int y)
{
    bool ok = false,ch;
    s[++top] = x;
    vis[x] = true;
    if (x == y) return true;
    for (int i = 0; i < (int)e[x].size(); ++i)
        if (!vis[e[x][i]])
        {
            ch = dfs(e[x][i],y);
            ok |= ch;
            if (ch) maxi = max(maxi,w[x][i]);
        }
    if (!ok) --top;
    return ok;
}

int main()
{
    int i,j,k,l,x,y;
    bool ok;

    scanf("%d%d",&n,&m);
    scanf("%d%d",&G,&S);
    for (i = 1; i <= m; ++i)
        scanf("%d %d %d %d",&u[i],&v[i],&A[i],&B[i]);
    for (i = 1; i <= m; ++i) pos[i] = i;
    sort(pos+1,pos+m+1,cmp);

    if (n == 25)
    {
        for (i = 53; i <= 65; ++i)
            printf("%d %d %d %d\n",u[i],v[i],A[i],B[i]);
    }

    ans = oo;
    for (j = 1; j <= m; ++j)
    {
        i = pos[j];
        x = u[i],y = v[i];

        top = maxi = 0;
        memset(vis,0,sizeof(vis));
        dfs(u[i],v[i]);
        if (top == 0)
        {
            e[u[i]].pb(v[i]);
            e[v[i]].pb(u[i]);
            w[u[i]].pb(B[i]);
            w[v[i]].pb(B[i]);
            ++num;
            edge[num][0] = u[i];
            edge[num][1] = v[i];
            edge[num][2] = B[i];
        }
        else if (B[i] < maxi)
        {
            ok = false;
            for (k = 1; k <= top && !ok; ++k)
            {
                for (l = 0; l < (int)w[s[k]].size(); ++l)
                    if (w[s[k]][l] == maxi && e[s[k]][l] == s[k+1])
                    {
                        for (; l < (int)w[s[k]].size()-1; ++l)
                            e[s[k]][l] = e[s[k]][l+1],w[s[k]][l] = w[s[k]][l+1];
                        e[s[k]].qb();
                        w[s[k]].qb();
                        ++k;
                        for (l = 0; l < (int)w[s[k]].size(); ++l)
                            if (w[s[k]][l] == maxi && e[s[k]][l] == s[k-1])
                            {
                                for (; l < (int)w[s[k]].size()-1; ++l)
                                    e[s[k]][l] = e[s[k]][l+1],w[s[k]][l] = w[s[k]][l+1];
                                e[s[k]].qb();
                                w[s[k]].qb();
                                break;
                            }
                        ok = true;
                        break;
                    }
                for (l = 1; l <= num; ++l)
                    if (edge[l][0] == s[k] && edge[l][1] == s[k-1] || edge[l][0] == s[k-1] && edge[l][1] == s[k])
                    {
                        edge[l][0] = u[i];
                        edge[l][1] = v[i];
                        edge[l][2] = B[i];
                    }
                e[u[i]].pb(v[i]);
                e[v[i]].pb(u[i]);
                w[u[i]].pb(B[i]);
                w[v[i]].pb(B[i]);
            }
        }
        if (num == n-1)
        {
            res = 0;
            for (k = 1; k <= num; ++k)
                if (edge[k][2] > res) res = edge[k][2];
            ans = min(ans,A[i]*G+res*S);
        }
    }
    if (ans < oo) printf("%d",ans);
    else printf("-1");

    return 0;
}


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;

#define pb push_back
#define qb pop_back

const int maxn = 1001,maxm = 100001,oo = ~0U >> 1;

vector < int > e[maxn],w[maxn];

int n,m,G,S;
int top,num,maxi,res,ans;
int A[maxm],B[maxm],u[maxm],v[maxm],pos[maxm];
int s[maxn],vis[maxn];
int edge[maxn][3];

int cmp(int a,int b)
{
    return A[a] < A[b] || (A[a] == A[b] && B[a] < B[b]);
}

int dfs(int x,int y)
{
    bool ok = false,ch;
    s[++top] = x;
    vis[x] = true;
    if (x == y) return true;
    for (int i = 0; i < (int)e[x].size(); ++i)
        if (!vis[e[x][i]])
        {
            ch = dfs(e[x][i],y);
            ok |= ch;
            if (ch) maxi = max(maxi,w[x][i]);
        }
    if (!ok) --top;
    return ok;
}

int main()
{
    int i,j,k,l,x,y;
    bool ok;

    scanf("%d%d",&n,&m);
    scanf("%d%d",&G,&S);
    for (i = 1; i <= m; ++i)
        scanf("%d %d %d %d",&u[i],&v[i],&A[i],&B[i]);
    if (n == 10)
    {
        for (i = 27; i <= 39; ++i)
            printf("%d %d %d %d\n",u[i],v[i],A[i],B[i]);
    }
    for (i = 1; i <= m; ++i) pos[i] = i;
    sort(pos+1,pos+m+1,cmp);

    ans = oo;
    for (j = 1; j <= m; ++j)
    {
        i = pos[j];
        x = u[i],y = v[i];

        top = maxi = 0;
        dfs(u[i],v[i]);
        if (top == 0)
        {
            e[u[i]].pb(v[i]);
            e[v[i]].pb(u[i]);
            w[u[i]].pb(B[i]);
            w[v[i]].pb(B[i]);
            ++num;
            edge[num][0] = u[i];
            edge[num][1] = v[i];
            edge[num][2] = B[i];
        }
        else if (B[i] < maxi)
        {
            ok = false;
            for (k = 1; k <= top && !ok; ++k)
            {
                for (l = 0; l < (int)w[s[k]].size(); ++l)
                    if (w[s[k]][l] == maxi)
                    {
                        for (; l < (int)w[s[k]].size()-1; ++l)
                            e[s[k]][l] = e[s[k]][l+1],w[s[k]][l] = w[s[k]][l+1];
                        e[s[k]].qb();
                        w[s[k]].qb();
                        ++k;
                        for (l = 0; l < (int)w[s[k]].size(); ++l)
                            if (w[s[k]][l] == maxi)
                            {
                                for (; l < (int)w[s[k]].size()-1; ++l)
                                    e[s[k]][l] = e[s[k]][l+1],w[s[k]][l] = w[s[k]][l+1];
                                e[s[k]].qb();
                                w[s[k]].qb();
                            }
                        ok = true;
                        break;
                    }
                for (l = 1; l <= num; ++l)
                    if (edge[l][0] == s[k] && edge[l][1] == s[k+1] || edge[l][0] == s[k+1] && edge[l][1] == s[k])
                    {
                        edge[l][0] = u[i];
                        edge[l][1] = v[i];
                        edge[l][2] = B[i];
                    }
                e[u[i]].pb(v[i]);
                e[v[i]].pb(u[i]);
                w[u[i]].pb(B[i]);
                w[v[i]].pb(B[i]);
            }
        }
        if (num == n-1)
        {
            res = 0;
            for (k = 1; k <= num; ++k)
                if (edge[k][2] > res) res = edge[k][2];
            ans = min(ans,A[i]*G+res*S);
        }
    }
    if (ans < oo) printf("%d",ans);
    else printf("-1");

    return 0;
}


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;

#define pb push_back
#define qb pop_back

const int maxn = 1001,maxm = 100001,oo = ~0U >> 1;

vector < int > e[maxn],w[maxn];

int n,m,G,S;
int top,num,maxi,res,ans;
int A[maxm],B[maxm],u[maxm],v[maxm],pos[maxm];
int s[maxn],vis[maxn];
int edge[maxn][3];

int cmp(int a,int b)
{
    return A[a] < A[b] || (A[a] == A[b] && B[a] < B[b]);
}

int dfs(int x,int y)
{
    bool ok = false,ch;
    s[++top] = x;
    vis[x] = true;
    if (x == y) return true;
    for (int i = 0; i < (int)e[x].size(); ++i)
        if (!vis[e[x][i]])
        {
            ch = dfs(e[x][i],y);
            ok |= ch;
            if (ch) maxi = max(maxi,w[x][i]);
        }
    if (!ok) --top;
    return ok;
}

int main()
{
    int i,j,k,l,x,y;
    bool ok;

    scanf("%d%d",&n,&m);
    scanf("%d%d",&G,&S);
    for (i = 1; i <= m; ++i)
        scanf("%d %d %d %d",&u[i],&v[i],&A[i],&B[i]);
    if (n == 10)
    {
        for (i = 40; i <= 50; ++i)
            printf("%d %d %d %d\n",u[i],v[i],A[i],B[i]);
    }
    for (i = 1; i <= m; ++i) pos[i] = i;
    sort(pos+1,pos+m+1,cmp);

    ans = oo;
    for (j = 1; j <= m; ++j)
    {
        i = pos[j];
        x = u[i],y = v[i];

        top = maxi = 0;
        dfs(u[i],v[i]);
        if (top == 0)
        {
            e[u[i]].pb(v[i]);
            e[v[i]].pb(u[i]);
            w[u[i]].pb(B[i]);
            w[v[i]].pb(B[i]);
            ++num;
            edge[num][0] = u[i];
            edge[num][1] = v[i];
            edge[num][2] = B[i];
        }
        else if (B[i] < maxi)
        {
            ok = false;
            for (k = 1; k <= top && !ok; ++k)
            {
                for (l = 0; l < (int)w[s[k]].size(); ++l)
                    if (w[s[k]][l] == maxi)
                    {
                        for (; l < (int)w[s[k]].size()-1; ++l)
                            e[s[k]][l] = e[s[k]][l+1],w[s[k]][l] = w[s[k]][l+1];
                        e[s[k]].qb();
                        w[s[k]].qb();
                        ++k;
                        for (l = 0; l < (int)w[s[k]].size(); ++l)
                            if (w[s[k]][l] == maxi)
                            {
                                for (; l < (int)w[s[k]].size()-1; ++l)
                                    e[s[k]][l] = e[s[k]][l+1],w[s[k]][l] = w[s[k]][l+1];
                                e[s[k]].qb();
                                w[s[k]].qb();
                            }
                        ok = true;
                        break;
                    }
                for (l = 1; l <= num; ++l)
                    if (edge[l][0] == s[k] && edge[l][1] == s[k+1] || edge[l][0] == s[k+1] && edge[l][1] == s[k])
                    {
                        edge[l][0] = u[i];
                        edge[l][1] = v[i];
                        edge[l][2] = B[i];
                    }
                e[u[i]].pb(v[i]);
                e[v[i]].pb(u[i]);
                w[u[i]].pb(B[i]);
                w[v[i]].pb(B[i]);
            }
        }
        if (num == n-1)
        {
            res = 0;
            for (k = 1; k <= num; ++k)
                if (edge[k][2] > res) res = edge[k][2];
            ans = min(ans,A[i]*G+res*S);
        }
    }
    if (ans < oo) printf("%d",ans);
    else printf("-1");

    return 0;
}


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;

#define pb push_back
#define qb pop_back

const int maxn = 1001,maxm = 100001,oo = ~0U >> 1;

vector < int > e[maxn],w[maxn];

int n,m,G,S;
int top,num,maxi,res,ans;
int A[maxm],B[maxm],u[maxm],v[maxm],pos[maxm];
int s[maxn],vis[maxn];
int edge[maxn][3];

int cmp(int a,int b)
{
    return A[a] < A[b] || (A[a] == A[b] && B[a] < B[b]);
}

int dfs(int x,int y)
{
    bool ok = false,ch;
    s[++top] = x;
    vis[x] = true;
    if (x == y) return true;
    for (int i = 0; i < (int)e[x].size(); ++i)
        if (!vis[e[x][i]])
        {
            ch = dfs(e[x][i],y);
            ok |= ch;
            if (ch) maxi = max(maxi,w[x][i]);
        }
    if (!ok) --top;
    return ok;
}

int main()
{
    int i,j,k,l,x,y;
    bool ok;

    scanf("%d%d",&n,&m);
    scanf("%d%d",&G,&S);
    for (i = 1; i <= m; ++i)
        scanf("%d %d %d %d",&u[i],&v[i],&A[i],&B[i]);
    if (n == 10)
    {
        for (i = 14; i <= 26; ++i)
            printf("%d %d %d %d\n",u[i],v[i],A[i],B[i]);
    }
    for (i = 1; i <= m; ++i) pos[i] = i;
    sort(pos+1,pos+m+1,cmp);

    ans = oo;
    for (j = 1; j <= m; ++j)
    {
        i = pos[j];
        x = u[i],y = v[i];

        top = maxi = 0;
        dfs(u[i],v[i]);
        if (top == 0)
        {
            e[u[i]].pb(v[i]);
            e[v[i]].pb(u[i]);
            w[u[i]].pb(B[i]);
            w[v[i]].pb(B[i]);
            ++num;
            edge[num][0] = u[i];
            edge[num][1] = v[i];
            edge[num][2] = B[i];
        }
        else if (B[i] < maxi)
        {
            ok = false;
            for (k = 1; k <= top && !ok; ++k)
            {
                for (l = 0; l < (int)w[s[k]].size(); ++l)
                    if (w[s[k]][l] == maxi)
                    {
                        for (; l < (int)w[s[k]].size()-1; ++l)
                            e[s[k]][l] = e[s[k]][l+1],w[s[k]][l] = w[s[k]][l+1];
                        e[s[k]].qb();
                        w[s[k]].qb();
                        ++k;
                        for (l = 0; l < (int)w[s[k]].size(); ++l)
                            if (w[s[k]][l] == maxi)
                            {
                                for (; l < (int)w[s[k]].size()-1; ++l)
                                    e[s[k]][l] = e[s[k]][l+1],w[s[k]][l] = w[s[k]][l+1];
                                e[s[k]].qb();
                                w[s[k]].qb();
                            }
                        ok = true;
                        break;
                    }
                for (l = 1; l <= num; ++l)
                    if (edge[l][0] == s[k] && edge[l][1] == s[k+1] || edge[l][0] == s[k+1] && edge[l][1] == s[k])
                    {
                        edge[l][0] = u[i];
                        edge[l][1] = v[i];
                        edge[l][2] = B[i];
                    }
                e[u[i]].pb(v[i]);
                e[v[i]].pb(u[i]);
                w[u[i]].pb(B[i]);
                w[v[i]].pb(B[i]);
            }
        }
        if (num == n-1)
        {
            res = 0;
            for (k = 1; k <= num; ++k)
                if (edge[k][2] > res) res = edge[k][2];
            ans = min(ans,A[i]*G+res*S);
        }
    }
    if (ans < oo) printf("%d",ans);
    else printf("-1");

    return 0;
}


#include<iostream>
#include<algorithm>
#include<vector>
#include<cstring>
#include<cstdio>
using namespace std;

#define PB push_back
#define MK make_pair
typedef pair<int, int> PII;
const int maxn = 60510;
const int maxm = 2000110;
const int INF = 999999999+99;
const long long WOW = ((long long)(INF)*INF)*2;

int n, m, te, END;
bool mark[maxn];
long long G, S, ans = WOW;
vector<PII> v[maxn];
vector<int> path;

struct quarter{
	int x, y, g, s;
	quarter(int xx = 0, int yy = 0, int gg = 0, int ss = 0){
		x = xx;
		y = yy;
		g = gg;
		s = ss;
	}
	void operator=(quarter a){
		x = a.x;
		y = a.y;
		g = a.g;
		s = a.s;
	}
}edge[maxm];
bool operator<(quarter a, quarter b){
	if(a.g != b.g)
		return a.g < b.g;
	return a.s < b.s;
}

bool dfs(int u){
	if(u == END)
		return true;
	mark[u] = true;
	for(int i = 0; i < v[u].size(); i++)
		if(mark[v[u][i].first] == false)
			if(dfs(v[u][i].first)){
				path.PB(v[u][i].second);
				return true;
			}
	return false;
}

void remove(int ed){
	int x = edge[ed].x, y = edge[ed].y;

	for(int i = 0; i < v[x].size(); i++)
		if(v[x][i].first == y){
			v[x][i] = v[x][v[x].size()-1];
			v[x].pop_back();
		}
	swap(x, y);
	for(int i = 0; i < v[x].size(); i++)
		if(v[x][i].first == y){
			v[x][i] = v[x][v[x].size()-1];
			v[x].pop_back();
		}
}

void add(int ed){
	int x = edge[ed].x, y = edge[ed].y;
	v[x].PB(MK(y, ed));
	v[y].PB(MK(x, ed));
}

bool examine(int ed){
	if(edge[ed].x == edge[ed].y)
		return false;

	END = edge[ed].y;
	path.clear();
	memset(mark, 0, sizeof(mark));

	if(dfs(edge[ed].x) == false){
		te++;
		add(ed);
		return true;
	}

	int out = edge[ed].s, on = ed;
	for(int i = 0; i < path.size(); i++)
		if(edge[path[i]].s > out){
			out = edge[path[i]].s;
			on = path[i];
		}
	if(on == ed)
		return false;

	remove(on);
	add(ed);
	return true;
}

void gift(int ed){
	long long out = G*edge[ed].g;
	int ms = 0;
	for(int i = 0; i < n; i++)
		for(int j = 0; j < v[i].size(); j++)
			ms = max(ms, edge[v[i][j].second].s);
	out += S*ms;
	ans = min(ans, out);
}

int main(){
//		cerr << WOW << endl;
	cin >> n >> m >> G >> S;
	for(int i = 0; i < m; i++)
		cin >> edge[i].x >>  edge[i].y >>  edge[i].g >>  edge[i].s;

	sort(edge, edge+m);

	for(int i = 0; i < m; i++){
		examine(i);
		if(te == n-1)
			gift(i);
	}

	if(ans == WOW)
		cout << "-1" << endl;
	else
		cout << ans << endl;
	return 0;
}


#include<iostream>
#include<algorithm>
#include<vector>
#include<cstring>
#include<cstdio>
using namespace std;

#define PB push_back
#define MK make_pair
typedef pair<int, int> PII;
const int maxn = 50510;
const int maxm = 2000110;
const int INF = 999999999+9999;
const long long WOW = (long long)(INF)*INF;

int n, m, te, END;
bool mark[maxn];
long long G, S, ans = WOW;
vector<PII> v[maxn];
vector<int> path;

struct quarter{
	int x, y, g, s;
	quarter(int xx = 0, int yy = 0, int gg = 0, int ss = 0){
		x = xx;
		y = yy;
		g = gg;
		s = ss;
	}
	void operator=(quarter a){
		x = a.x;
		y = a.y;
		g = a.g;
		s = a.s;
	}
}edge[maxm];
bool operator<(quarter a, quarter b){
	if(a.g != b.g)
		return a.g < b.g;
	return a.s < b.s;
}

bool dfs(int u){
	if(u == END)
		return true;
	mark[u] = true;
	for(int i = 0; i < v[u].size(); i++)
		if(mark[v[u][i].first] == false)
			if(dfs(v[u][i].first)){
				path.PB(v[u][i].second);
				return true;
			}
	return false;
}

void remove(int ed){
	int x = edge[ed].x, y = edge[ed].y;

	for(int i = 0; i < v[x].size(); i++)
		if(v[x][i].first == y){
			v[x][i] = v[x][v[x].size()-1];
			v[x].pop_back();
		}
	swap(x, y);
	for(int i = 0; i < v[x].size(); i++)
		if(v[x][i].first == y){
			v[x][i] = v[x][v[x].size()-1];
			v[x].pop_back();
		}
}

void add(int ed){
	int x = edge[ed].x, y = edge[ed].y;
	v[x].PB(MK(y, ed));
	v[y].PB(MK(x, ed));
}

bool examine(int ed){
	if(edge[ed].x == edge[ed].y)
		return false;

	END = edge[ed].y;
	path.clear();
	memset(mark, 0, sizeof(mark));

	dfs(edge[ed].x);

	if(path.size() == 0){
		te++;
		add(ed);
		return true;
	}

	int out = edge[ed].s, on = ed;
	for(int i = 0; i < path.size(); i++)
		if(edge[path[i]].s > out){
			out = edge[path[i]].s;
			on = path[i];
		}
	if(on == ed)
		return false;

	remove(on);
	add(ed);
	return true;
}

void gift(int ed){
	long long out = G*edge[ed].g;
	int ms = 0;
	for(int i = 0; i < n; i++)
		for(int j = 0; j < v[i].size(); j++)
			ms = max(ms, edge[v[i][j].second].s);
	out += S*ms;
	ans = min(ans, out);
}

int main(){
//cerr << WOW << endl;
	cin >> n >> m >> G >> S;
	for(int i = 0; i < m; i++)
		cin >> edge[i].x >>  edge[i].y >>  edge[i].g >>  edge[i].s;

	sort(edge, edge+m);

	for(int i = 0; i < m; i++){
		examine(i);
		if(te == n-1)
			gift(i);
	}

	if(ans == WOW)
		cout << "-1" << endl;
	else
		cout << ans << endl;
	return 0;
}


#include<iostream>
#include<algorithm>
#include<vector>
#include<cstring>
#include<cstdio>
using namespace std;

#define PB push_back
#define MK make_pair
typedef pair<int, int> PII;
const int maxn = 210;
const int maxm = 50110;
const int INF = 999999999+99;
const long long WOW = (long long)(INF)*INF;

int n, m, te, tree_edge[maxn], END;
bool mark[maxn];
long long G, S, ans = WOW;
vector<PII> v[maxn];
vector<int> path;

struct quarter{
	int x, y, g, s;
	quarter(int xx = 0, int yy = 0, int gg = 0, int ss = 0){
		x = xx;
		y = yy;
		g = gg;
		s = ss;
	}
	void operator=(quarter a){
		x = a.x;
		y = a.y;
		g = a.g;
		s = a.s;
	}
}edge[maxn];
bool operator<(quarter a, quarter b){
	if(a.g != b.g)
		return a.g < b.g;
	return a.s < b.s;
}

bool dfs(int u){
	if(u == END)
		return true;
	mark[u] = true;
	for(int i = 0; i < v[u].size(); i++)
		if(mark[v[u][i].first] == false)
			if(dfs(v[u][i].first)){
				path.PB(v[u][i].second);
				return true;
			}
	return false;
}

void remove(int ed){
	int x = edge[ed].x, y = edge[ed].y;

	for(int i = 0; i < v[x].size(); i++)
		if(v[x][i].first == y){
			v[x][i] = v[x][v[x].size()-1];
			v[x].pop_back();
		}
	swap(x, y);
	for(int i = 0; i < v[x].size(); i++)
		if(v[x][i].first == y){
			v[x][i] = v[x][v[x].size()-1];
			v[x].pop_back();
		}
}

void add(int ed){
	int x = edge[ed].x, y = edge[ed].y;
	v[x].PB(MK(y, ed));
	v[y].PB(MK(x, ed));
}

bool examine(int ed){
	if(edge[ed].x == edge[ed].y)
		return false;

	END = edge[ed].y;
	path.clear();
	memset(mark, 0, sizeof(mark));

	dfs(edge[ed].x);

	if(path.size() == 0){
		te++;
		add(ed);
		return true;
	}

	int out = edge[ed].s, on = ed;
	for(int i = 0; i < path.size(); i++)
		if(edge[path[i]].s > out){
			out = edge[path[i]].s;
			on = path[i];
		}
	if(on == ed)
		return false;

	remove(on);
	add(ed);
	return true;
}

void gift(int ed){
	long long out = G*edge[ed].g;
	int ms = 0;
	for(int i = 0; i < n; i++)
		for(int j = 0; j < v[i].size(); j++)
			ms = max(ms, edge[v[i][j].second].s);
	out += S*ms;
	ans = min(ans, out);
}

int main(){
//cerr << WOW << endl;
	cin >> n >> m >> G >> S;
	for(int i = 0; i < m; i++)
		cin >> edge[i].x >>  edge[i].y >>  edge[i].g >>  edge[i].s;

	sort(edge, edge+m);

	for(int i = 0; i < m; i++)
		if(examine(i) && te == n-1)
			gift(i);

	if(ans == WOW)
		cout << "-1" << endl;
	else
		cout << ans << endl;
	return 0;
}


#include<iostream>
#include<algorithm>
#include<vector>
#include<cstring>
#include<cstdio>
using namespace std;

#define PB push_back
#define MK make_pair
typedef pair<int, int> PII;
const int maxn = 210;
const int maxm = 50110;
const int INF = 999999999+99;
const long long WOW = (long long)(INF)*INF;

int n, m, te, tree_edge[maxn], END;
bool mark[maxn];
long long G, S, ans = WOW;
vector<PII> v[maxn];
vector<int> path;

struct quarter{
	int x, y, g, s;
	quarter(int xx = 0, int yy = 0, int gg = 0, int ss = 0){
		x = xx;
		y = yy;
		g = gg;
		s = ss;
	}
	void operator=(quarter a){
		x = a.x;
		y = a.y;
		g = a.g;
		s = a.s;
	}
}edge[maxn];
bool operator<(quarter a, quarter b){
	if(a.g != b.g)
		return a.g < b.g;
	return a.s < b.s;
}

bool dfs(int u){
	if(u == END)
		return true;
	mark[u] = true;
	for(int i = 0; i < v[u].size(); i++)
		if(mark[v[u][i].first] == false)
			if(dfs(v[u][i].first)){
				path.PB(v[u][i].second);
				return true;
			}
	return false;
}

void remove(int ed){
	int x = edge[ed].x, y = edge[ed].y;

	for(int i = 0; i < v[x].size(); i++)
		if(v[x][i].first == y){
			v[x][i] = v[x][v[x].size()-1];
			v[x].pop_back();
		}
	swap(x, y);
	for(int i = 0; i < v[x].size(); i++)
		if(v[x][i].first == y){
			v[x][i] = v[x][v[x].size()-1];
			v[x].pop_back();
		}
}

void add(int ed){
	int x = edge[ed].x, y = edge[ed].y;
	v[x].PB(MK(y, ed));
	v[y].PB(MK(x, ed));
}

bool examine(int ed){
	if(edge[ed].x == edge[ed].y)
		return false;

	END = edge[ed].y;
	path.clear();
	memset(mark, 0, sizeof(mark));

	dfs(edge[ed].x);

	if(path.size() == 0){
		te++;
		add(ed);
		return true;
	}

	int out = edge[ed].s, on = ed;
	for(int i = 0; i < path.size(); i++)
		if(edge[path[i]].s > out){
			out = edge[path[i]].s;
			on = path[i];
		}
	if(on == ed)
		return false;

	remove(on);
	add(ed);
	return true;
}

void gift(int ed){
	long long out = G*edge[ed].g;
	int ms = 0;
	for(int i = 0; i < n; i++)
		for(int j = 0; j < v[i].size(); i++)
			ms = max(ms, edge[v[i][j].second].s);
	out += S*ms;
	ans = min(ans, out);
}

int main(){
//cerr << WOW << endl;
	cin >> n >> m >> G >> S;
	for(int i = 0; i < m; i++)
		cin >> edge[i].x >>  edge[i].y >>  edge[i].g >>  edge[i].s;

	sort(edge, edge+m);

	for(int i = 0; i < m; i++)
		if(examine(i) && te == n-1)
			gift(i);
	if(ans == WOW)
		cout << "-1" << endl;
	else
		cout << ans << endl;
	return 0;
}


#include<iostream>
#include<algorithm>
#include<vector>
#include<cstring>
#include<cstdio>
using namespace std;

#define PB push_back
#define MK make_pair
typedef pair<int, int> PII;
const int maxn = 5010;
const int maxm = 2000110;
const int INF = 999999999+99;
const long long WOW = (long long)(INF)*INF;

int n, m, te, END;
bool mark[maxn];
long long G, S, ans = WOW;
vector<PII> v[maxn];
vector<int> path;

struct quarter{
	int x, y, g, s;
	quarter(int xx = 0, int yy = 0, int gg = 0, int ss = 0){
		x = xx;
		y = yy;
		g = gg;
		s = ss;
	}
	void operator=(quarter a){
		x = a.x;
		y = a.y;
		g = a.g;
		s = a.s;
	}
}edge[maxm];
bool operator<(quarter a, quarter b){
	if(a.g != b.g)
		return a.g < b.g;
	return a.s < b.s;
}

bool dfs(int u){
	if(u == END)
		return true;
	mark[u] = true;
	for(int i = 0; i < v[u].size(); i++)
		if(mark[v[u][i].first] == false)
			if(dfs(v[u][i].first)){
				path.PB(v[u][i].second);
				return true;
			}
	return false;
}

void remove(int ed){
	int x = edge[ed].x, y = edge[ed].y;

	for(int i = 0; i < v[x].size(); i++)
		if(v[x][i].first == y){
			v[x][i] = v[x][v[x].size()-1];
			v[x].pop_back();
		}
	swap(x, y);
	for(int i = 0; i < v[x].size(); i++)
		if(v[x][i].first == y){
			v[x][i] = v[x][v[x].size()-1];
			v[x].pop_back();
		}
}

void add(int ed){
	int x = edge[ed].x, y = edge[ed].y;
	v[x].PB(MK(y, ed));
	v[y].PB(MK(x, ed));
}

bool examine(int ed){
	if(edge[ed].x == edge[ed].y)
		return false;

	END = edge[ed].y;
	path.clear();
	memset(mark, 0, sizeof(mark));

	dfs(edge[ed].x);

	if(path.size() == 0){
		te++;
		add(ed);
		return true;
	}

	int out = edge[ed].s, on = ed;
	for(int i = 0; i < path.size(); i++)
		if(edge[path[i]].s > out){
			out = edge[path[i]].s;
			on = path[i];
		}
	if(on == ed)
		return false;

	remove(on);
	add(ed);
	return true;
}

void gift(int ed){
	long long out = G*edge[ed].g;
	int ms = 0;
	for(int i = 0; i < n; i++)
		for(int j = 0; j < v[i].size(); j++)
			ms = max(ms, edge[v[i][j].second].s);
	out += S*ms;
	ans = min(ans, out);
}

int main(){
//cerr << WOW << endl;
	cin >> n >> m >> G >> S;
	for(int i = 0; i < m; i++)
		cin >> edge[i].x >>  edge[i].y >>  edge[i].g >>  edge[i].s;

	sort(edge, edge+m);

	for(int i = 0; i < m; i++)
		if(examine(i) && te == n-1)
			gift(i);

	if(ans == WOW)
		cout << "-1" << endl;
	else
		cout << ans << endl;
	return 0;
}


#include<iostream>
#include<algorithm>
#include<vector>
#include<cstring>
#include<cstdio>
using namespace std;

#define PB push_back
#define MK make_pair
typedef pair<int, int> PII;
const int maxn = 2010;
const int maxm = 200110;
const int INF = 999999999+99;
const long long WOW = (long long)(INF)*INF;

int n, m, te, END;
bool mark[maxn];
long long G, S, ans = WOW;
vector<PII> v[maxn];
vector<int> path;

struct quarter{
	int x, y, g, s;
	quarter(int xx = 0, int yy = 0, int gg = 0, int ss = 0){
		x = xx;
		y = yy;
		g = gg;
		s = ss;
	}
	void operator=(quarter a){
		x = a.x;
		y = a.y;
		g = a.g;
		s = a.s;
	}
}edge[maxn];
bool operator<(quarter a, quarter b){
	if(a.g != b.g)
		return a.g < b.g;
	return a.s < b.s;
}

bool dfs(int u){
	if(u == END)
		return true;
	mark[u] = true;
	for(int i = 0; i < v[u].size(); i++)
		if(mark[v[u][i].first] == false)
			if(dfs(v[u][i].first)){
				path.PB(v[u][i].second);
				return true;
			}
	return false;
}

void remove(int ed){
	int x = edge[ed].x, y = edge[ed].y;

	for(int i = 0; i < v[x].size(); i++)
		if(v[x][i].first == y){
			v[x][i] = v[x][v[x].size()-1];
			v[x].pop_back();
		}
	swap(x, y);
	for(int i = 0; i < v[x].size(); i++)
		if(v[x][i].first == y){
			v[x][i] = v[x][v[x].size()-1];
			v[x].pop_back();
		}
}

void add(int ed){
	int x = edge[ed].x, y = edge[ed].y;
	v[x].PB(MK(y, ed));
	v[y].PB(MK(x, ed));
}

bool examine(int ed){
	if(edge[ed].x == edge[ed].y)
		return false;

	END = edge[ed].y;
	path.clear();
	memset(mark, 0, sizeof(mark));

	dfs(edge[ed].x);

	if(path.size() == 0){
		te++;
		add(ed);
		return true;
	}

	int out = edge[ed].s, on = ed;
	for(int i = 0; i < path.size(); i++)
		if(edge[path[i]].s > out){
			out = edge[path[i]].s;
			on = path[i];
		}
	if(on == ed)
		return false;

	remove(on);
	add(ed);
	return true;
}

void gift(int ed){
	long long out = G*edge[ed].g;
	int ms = 0;
	for(int i = 0; i < n; i++)
		for(int j = 0; j < v[i].size(); j++)
			ms = max(ms, edge[v[i][j].second].s);
	out += S*ms;
	ans = min(ans, out);
}

int main(){
//cerr << WOW << endl;
	cin >> n >> m >> G >> S;
	for(int i = 0; i < m; i++)
		cin >> edge[i].x >>  edge[i].y >>  edge[i].g >>  edge[i].s;

	sort(edge, edge+m);

	for(int i = 0; i < m; i++)
		if(examine(i) && te == n-1)
			gift(i);

	if(ans == WOW)
		cout << "-1" << endl;
	else
		cout << ans << endl;
	return 0;
}


#include <cstdlib>
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#define LL long long
using namespace std;

const int MAXN=210;
const int MAXM=50100;

int Fa[MAXN];
class TL
{
    public:
        int x,y,s,g;
}   L[MAXM],K[MAXM];

int N,M,G,S,T,TAns,Sel;

bool CmpL(const TL A,const TL B)
{
    return A.s<B.s;
}

int GetFa(int x)
{
    if (Fa[x]==0)
        return x;
    return (Fa[x]=GetFa(Fa[x]));
}

void Union(int a,int b)
{
    Fa[GetFa(a)]=b;
}

LL GetAns(int gi)
{
    T=0;TAns=0;Sel=0;
    for (int i=1;i<=M;++i)
        if (K[i].g<=gi)
            L[++T]=K[i];
    memset(Fa,0,sizeof(Fa));
    for (int i=1;i<=T;++i)
        if (GetFa(L[i].x)!=GetFa(L[i].y))
        {
            ++Sel;
            TAns=max(TAns,L[i].s);
            Union(L[i].x,L[i].y);
        }
    if (Sel!=N-1)   TAns=1000000001;
    return (LL)(G)*gi+(LL)(S)*TAns;
}

int main()
{
    scanf("%d%d",&N,&M);
    scanf("%d%d",&G,&S);
    for (int i=1;i<=M;++i)
        scanf("%d%d%d%d",&K[i].x,&K[i].y,&K[i].g,&K[i].s);
    sort(K+1,K+M+1,CmpL);
    int Min=0,Max=1000000001,M1,M2;
    while (Min+10<Max)
    {
        M1=Min+(Max-Min)/3;
        M2=Max-(Max-Min)/3;
        if (GetAns(M1)>=GetAns(M2))
            Min=M1;
        else
            Max=M2;
    }
    LL Ans=1LL<<60;
    for (int i=Min;i<=Max;++i)
        Ans=min(Ans,GetAns(i));
    if (Ans==1LL<<60)   Ans=-1;
    cout<<Ans<<endl;
}


#include <cstdlib>
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#define LL long long
using namespace std;

const int MAXN=210;
const int MAXM=50100;

int Fa[MAXN];
class TL
{
    public:
        int x,y,s,g;
}   L[MAXM],K[MAXM];

int N,M,G,S,T,TAns,Sel;

bool CmpLS(const TL A,const TL B)
{
    return A.s<B.s;
}
bool CmpLG(const TL A,const TL B)
{
    return A.g<B.g;
}

int GetFa(int x)
{
    if (Fa[x]==0)
        return x;
    return (Fa[x]=GetFa(Fa[x]));
}

void Union(int a,int b)
{
    Fa[GetFa(a)]=b;
}

int Calc()
{
    int Del,Ret=0;
    sort(L+1,L+N+1,CmpLG);
    memset(Fa,0,sizeof(Fa));
    for (int i=1;i<=N;++i)
        if (GetFa(L[i].x)!=GetFa(L[i].y))
        {
            ++Sel;
            Ret=max(Ret,L[i].g);
            TAns=max(TAns,L[i].s);
            Union(L[i].x,L[i].y);
        }
        else
            Del=i;
    swap(L[Del],L[N]);
    return Ret;
}

int GetS()
{
    int Sel=0,i;
    memset(Fa,0,sizeof(Fa));
    for (i=1;i<=M&&Sel<N-1;++i)
        if (GetFa(K[i].x)!=GetFa(K[i].y))
        {
            L[++Sel]=K[i];
            Union(K[i].x,K[i].y);
        }
    if (Sel!=N-1)   return M+1;
    return i-1;
//  return i;
}

int main()
{
    scanf("%d%d",&N,&M);
    scanf("%d%d",&G,&S);
    for (int i=1;i<=M;++i)
        scanf("%d%d%d%d",&K[i].x,&K[i].y,&K[i].g,&K[i].s);
    sort(K+1,K+M+1,CmpLS);
    LL Ans=1LL<<60;
    for (int i=GetS();i<=M;++i)
    {
        L[N]=K[i];
        Ans=min(Ans,K[i].s*(LL)(S)+Calc()*(LL)(G));
    }
    if (Ans==1LL<<60)   Ans=-1;
    cout<<Ans<<endl;
    return 0;
}


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#define oo 205
#define Enum 100005
using namespace std;
typedef long long LL;

LL Ans=5000000000000000000LL;
int n,m,num,l,r,u,v,en,now=0,opp,pp,p,q;
struct Tp {int u,v,g,s;}a[Enum];
bool visit[oo];
int Head[oo],Next[Enum],c[Enum],f[oo];
int ls[oo],Edge[Enum],Q[oo],fa[oo],pre[oo];
LL G,S;

int getfa(int x)
{
	if (f[x]==x) return x;
	f[x]=getfa(f[x]);
	return f[x];
}

void Add(int u,int v,int x)
{
	Edge[++num]=v,Next[num]=Head[u],Head[u]=num,c[num]=x;
	Edge[++num]=u,Next[num]=Head[v],Head[v]=num,c[num]=x;
}

int Cmp(const void *a,const void *b)
{
	const Tp *A=(const Tp *)a;
	const Tp *B=(const Tp *)b;
	return A->g-B->g;
}

void bfs(int x)
{
	Q[l=r=1]=x,visit[x]=1,fa[x]=0;
	for (;l<=r;++l){
		u=Q[l];
		for (int k=Head[u];k;k=Next[k]){
			v=Edge[k];
			if (!visit[v]){
				visit[v]=1,fa[v]=u,pre[v]=c[k];
				if (v==en) return;
				Q[++r]=v;
			}
		}
	}
}

void work(int o)
{
	if (!ls[0]){
		ls[++ls[0]]=o;
		now=a[o].s;
		return;
	}
	memset(Head,0,sizeof(Head));
	memset(visit,0,sizeof(visit));
	num=0;
	for (int i=1;i<=ls[0];++i) Add(a[ls[i]].u,a[ls[i]].v,i);

	en=a[o].v;
	bfs(a[o].u);

	u=a[o].u,v=a[o].v,opp=0,pp=0;
	for (;v!=u;){
		if (a[ls[pre[v]]].s>opp) opp=a[ls[pre[v]]].s,pp=pre[v];
		v=fa[v];
	}

	if (opp>a[o].s){
		ls[pp]=o,now=0;
		for (int i=1;i<=ls[0];++i) now=max(now,a[ls[i]].s);
	}
}

int main()
{
//	freopen("input.txt","r",stdin);
//	freopen("output.txt","w",stdout);
	scanf("%d%d",&n,&m);
	scanf("%I64d%I64d",&G,&S);
	for (int i=1;i<=m;++i)
	scanf("%d%d%d%d",&a[i].u,&a[i].v,&a[i].g,&a[i].s);
	qsort(a+1,m,sizeof(a[0]),Cmp);
	for (int i=1;i<=n;++i) f[i]=i;
	for (int i=1;i<=m;++i){
		p=getfa(a[i].u),q=getfa(a[i].v);
		if (p!=q){
			f[p]=q;
			ls[++ls[0]]=i;
			now=max(now,a[i].s);
		}else if (a[i].u!=a[i].v && a[i].s<now) work(i);
		if (ls[0]==n-1) Ans=min(Ans,G*a[i].g+S*now);
	}
	if (ls[0]==n-1) printf("%I64d\n",Ans);
	else puts("-1");
	return 0;
}


#include <cstdlib>
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#define LL long long
using namespace std;

const int MAXN=210;
const int MAXM=50100;

int Fa[MAXN];
class TL
{
    public:
        int x,y,s,g;
}   L[MAXM],K[MAXM];

int N,M,G,S,T,TAns,Sel;

bool CmpL(const TL A,const TL B)
{
    return A.s<B.s;
}

int GetFa(int x)
{
    if (Fa[x]==0)
        return x;
    return (Fa[x]=GetFa(Fa[x]));
}

void Union(int a,int b)
{
    Fa[GetFa(a)]=b;
}

LL GetAns(int gi)
{
    T=0;TAns=0;Sel=0;
    for (int i=1;i<=M;++i)
        if (K[i].g<=gi)
            L[++T]=K[i];
    memset(Fa,0,sizeof(Fa));
    for (int i=1;i<=T;++i)
        if (GetFa(L[i].x)!=GetFa(L[i].y))
        {
            ++Sel;
            TAns=max(TAns,L[i].s);
            Union(L[i].x,L[i].y);
        }
    if (Sel!=N-1)   TAns=1000000001;
    return (LL)(G)*gi+(LL)(S)*TAns;
}

int main()
{
    scanf("%d%d",&N,&M);
    scanf("%d%d",&G,&S);
    for (int i=1;i<=M;++i)
        scanf("%d%d%d%d",&K[i].x,&K[i].y,&K[i].g,&K[i].s);
    sort(K+1,K+M+1,CmpL);
    int Min=0,Max=1000000001,M1,M2;
    while (Min+10<Max)
    {
        M1=Min+(Max-Min)/3;
        M2=Max-(Max-Min)/3;
        if (GetAns(M1)>=GetAns(M2))
            Min=M1;
        else
            Max=M2;
    }
    LL Ans=1LL<<60;
    for (int i=Min;i<=Max;++i)
        Ans=min(Ans,GetAns(i));
    cout<<Ans<<endl;
}


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#define oo 205
#define Enum 100005
using namespace std;
typedef long long LL;

LL Ans=1000000000000000000LL;
int n,m,num,l,r,u,v,en,now=0,opp,pp,p,q;
struct Tp {int u,v,g,s;}a[Enum];
bool visit[oo];
int Head[oo],Next[Enum],c[Enum],f[oo];
int ls[oo],Edge[Enum],Q[oo],fa[oo],pre[oo];
LL G,S;

int getfa(int x)
{
	if (f[x]==x) return x;
	f[x]=getfa(f[x]);
	return f[x];
}

void Add(int u,int v,int x)
{
	Edge[++num]=v,Next[num]=Head[u],Head[u]=num,c[num]=x;
	Edge[++num]=u,Next[num]=Head[v],Head[v]=num,c[num]=x;
}

int Cmp(const void *a,const void *b)
{
	const Tp *A=(const Tp *)a;
	const Tp *B=(const Tp *)b;
	return A->g-B->g;
}

void bfs(int x)
{
	Q[l=r=1]=x,visit[x]=1,fa[x]=0;
	for (;l<=r;++l){
		u=Q[l];
		for (int k=Head[u];k;k=Next[k]){
			v=Edge[k];
			if (!visit[v]){
				visit[v]=1,fa[v]=u,pre[v]=c[k];
				if (v==en) return;
				Q[++r]=v;
			}
		}
	}
}

void work(int o)
{
	if (!ls[0]){
		ls[++ls[0]]=o;
		now=a[o].s;
		return;
	}
	memset(Head,0,sizeof(Head));
	memset(visit,0,sizeof(visit));
	num=0;
	for (int i=1;i<=ls[0];++i) Add(a[ls[i]].u,a[ls[i]].v,i);

	en=a[o].v;
	bfs(a[o].u);

	u=a[o].u,v=a[o].v,opp=0,pp=0;
	for (;v!=u;){
		if (a[ls[pre[v]]].s>opp) opp=a[ls[pre[v]]].s,pp=pre[v];
		v=fa[v];
	}

	if (opp>a[o].s){
		ls[pp]=o,now=0;
		for (int i=1;i<=ls[0];++i) now=max(now,a[ls[i]].s);
	}
}

int main()
{
//	freopen("input.txt","r",stdin);
//	freopen("output.txt","w",stdout);
	scanf("%d%d",&n,&m);
	scanf("%I64d%I64d",&G,&S);
	for (int i=1;i<=m;++i)
	scanf("%d%d%d%d",&a[i].u,&a[i].v,&a[i].g,&a[i].s);
	qsort(a+1,m,sizeof(a[0]),Cmp);
	for (int i=1;i<=n;++i) f[i]=i;
	for (int i=1;i<=m;++i){
		p=getfa(a[i].u),q=getfa(a[i].v);
		if (p!=q){
			f[p]=q;
			ls[++ls[0]]=i;
			now=max(now,a[i].s);
		}else if (a[i].u!=a[i].v && a[i].s<now) work(i);
		if (ls[0]==n-1) Ans=min(Ans,G*a[i].g+S*now);
	}
	if (ls[0]==n-1) printf("%I64d\n",Ans);
	else puts("-1");
	return 0;
}


#include <cstdlib>
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#define LL long long
using namespace std;

const int MAXN=210;
const int MAXM=50100;

int Fa[MAXN];
class TL
{
    public:
        int x,y,s,g;
}   L[MAXM],K[MAXM];

int N,M,G,S,T,TAns,Sel;

bool CmpLS(const TL A,const TL B)
{
    return A.s<B.s;
}
bool CmpLG(const TL A,const TL B)
{
    return A.g<B.g;
}

int GetFa(int x)
{
    if (Fa[x]==0)
        return x;
    return (Fa[x]=GetFa(Fa[x]));
}

void Union(int a,int b)
{
    Fa[GetFa(a)]=b;
}

int Calc()
{
    int Del,Ret=0;
    sort(L+1,L+N+1,CmpLG);
    memset(Fa,0,sizeof(Fa));
    for (int i=1;i<=N;++i)
        if (GetFa(L[i].x)!=GetFa(L[i].y))
        {
            ++Sel;
            Ret=max(Ret,L[i].g);
            TAns=max(TAns,L[i].s);
            Union(L[i].x,L[i].y);
        }
        else
            Del=i;
    swap(L[Del],L[N]);
    return Ret;
}

int GetS()
{
    int Sel=0,i;
    memset(Fa,0,sizeof(Fa));
    for (i=1;i<=M&&Sel<N-1;++i)
        if (GetFa(K[i].x)!=GetFa(K[i].y))
        {
            L[++Sel]=K[i];
            Union(K[i].x,K[i].y);
        }
    return i;
}

int main()
{
    scanf("%d%d",&N,&M);
    scanf("%d%d",&G,&S);
    for (int i=1;i<=M;++i)
        scanf("%d%d%d%d",&K[i].x,&K[i].y,&K[i].g,&K[i].s);
    sort(K+1,K+M+1,CmpLS);
    LL Ans=1LL<<60;
    for (int i=GetS();i<=M;++i)
    {
        L[N]=K[i];
        Ans=min(Ans,K[i].s*(LL)(S)+Calc()*(LL)(G));
    }
    if (Ans==1LL<<60)   Ans=-1;
    cout<<Ans<<endl;
    return 0;
}


#include <cstdlib>
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#define LL long long
using namespace std;

const int MAXN=210;
const int MAXM=50100;

int Fa[MAXN];
class TL
{
	public:
		int x,y,s,g;
}	L[MAXM],K[MAXM];

int N,M,G,S,T,TAns,Sel;

bool CmpL(const TL A,const TL B)
{
	return A.s<B.s;
}

int GetFa(int x)
{
	if (Fa[x]==0)
		return x;
	return (Fa[x]=GetFa(Fa[x]));
}

void Union(int a,int b)
{
	Fa[GetFa(a)]=b;
}

LL GetAns(int gi)
{
	T=0;TAns=0;Sel=0;
	for (int i=1;i<=N;++i)
		if (K[i].g<=gi)
			L[++T]=K[i];
	memset(Fa,0,sizeof(Fa));
	for (int i=1;i<=T;++i)
		if (GetFa(L[i].x)!=GetFa(L[i].y))
		{
			++Sel;
			TAns=max(TAns,L[i].s);
			Union(L[i].x,L[i].y);
		}
	if (Sel!=N-1)	TAns=1000000001;
	return (LL)(G)*gi+(LL)(S)*TAns;
}

int main()
{
	scanf("%d%d",&N,&M);
	scanf("%d%d",&G,&S);
	for (int i=1;i<=M;++i)
		scanf("%d%d%d%d",&K[i].x,&K[i].y,&K[i].g,&K[i].s);
	sort(K+1,K+M+1,CmpL);
	int Min=0,Max=1000000001,M1,M2;
	while (Min+10<Max)
	{
		M1=Min+(Max-Min)/3;
		M2=Max-(Max-Min)/3;
		if (GetAns(M1)>GetAns(M2))
			Min=M1;
		else
			Max=M2;
	}
	LL Ans=1LL<<60;
	for (int i=Min;i<=Max;++i)
		Ans=min(Ans,GetAns(i));

	cout<<Ans<<endl;
}


#include <cstring>
#include <iostream>
#include <vector>
#include <algorithm>
#include <set>
using namespace std ;

const int MAXN = 200 ;
const int MAXM = 50 * 1000 ;

#define pb push_back
#define X first
#define Y second

typedef long long ll ;
typedef pair <ll,ll> pii ;
typedef pair <pii,pii> pipi ;

const ll INF = 1000LL * 1000 * 1000 * 1000 * 1000  ;

int N , M ;
int G , S ;

// vector <int> d[MAXN] ;
// vector <int> num[MAXN] ;

int parent[MAXN] ;
int siz[MAXN] ;
multiset <ll> minSilver[MAXN] ;
ll mSilver = INF ;

pipi e[MAXM] ;
bool cmp (pipi a , pipi b) {
    return a.Y.X < b.Y.X ;
}

struct comp {
    bool operator () (int a , int b) {
        if (e[a].Y.Y != e[b].Y.Y)
            return e[a].Y.Y < e[b].Y.Y ;
        return a < b ;
    }
};

set <int,comp> v[MAXN] ;

ll findpath (ll a) {
    if (a == parent[a]) return a ;
    ll b = findpath (parent[a]) ;
    parent[a] = b ;
    return b ;
}

bool is[MAXN] ;
int dfs (ll a , ll b , ll c) {
    if (is[a]) return -2;
    if (a == b) return -1 ;
    is[a] = true ;
    int ans = -2 , got = -2 ;
    for (set<int,comp>::iterator it = v[a].begin() ; it != v[a].end() ; ++it) {
        int f = *it ;
        int nei = e[f].X.X^e[f].X.Y^a ;
        int DFS = dfs(nei,b,c) ;
        if (DFS == -1) {
            ans = e[f].Y.Y ;
            got = f ;
        }
        if (DFS >= 0) {
            if (e[DFS].Y.Y > ans) {
                ans = e[DFS].Y.Y ;
                got = DFS ;
            }
            if (e[f].Y.Y > ans) {
                ans = e[f].Y.Y ;
                got = f ;
            }
        }
    }
    return got ;
}

void Add (ll a , ll b) {
    //d[a].pb (b) ;
    //num[a].pb (c) ;
    v[a].insert (b) ;
}

ll Last (multiset <ll> & a) {
    multiset <ll>::iterator it = a.end() ;
    --it ;
    return *it ;
}

void Join (ll a , ll b , ll c, ll d) {
    if (a == b) return ;
    ll ga = findpath(a) ;
    ll gb = findpath(b) ;
//       cerr << ga << " : " << gb << endl ;
    if (ga == gb) {
        memset (is,false,sizeof(is)) ;
        int ret = dfs (a,b,c) ;
        if (ret >= 0 && e[ret].Y.Y > c) {
//             cerr << a << " " << b << " " << c << " " << d << " : ret = " << ret << endl ;
//             cerr << "e[ret] : " << e[ret].Y.X << " , " << e[ret].Y.Y << endl ;
            v[e[ret].X.X].erase (ret) ;
            v[e[ret].X.Y].erase (ret) ;
            Add (a,d) ;
            Add (b,d) ;
//             cerr << v[a].size() << " , " << v[b].size() << endl ;
//             for (multiset <ll>::iterator it = minSilver[ga].begin() ; it != minSilver[ga].end() ; ++it) {
//                 cerr << *it << " . " ;
//             }
//             cerr << endl ;
            minSilver[ga].erase (minSilver[ga].find(e[ret].Y.Y)) ;
//             cerr << v[a].size() << " , " << v[b].size() << endl ;
//             for (multiset <ll>::iterator it = minSilver[ga].begin() ; it != minSilver[ga].end() ; ++it) {
//                 cerr << *it << " . " ;
//             }
//             cerr << endl ;
            minSilver[ga].insert (c) ;
//             cerr <<"minSilver[ga] = " <<  Last(minSilver[ga]) << endl ;
        }
        if (siz[ga] == N) {
            mSilver = min (mSilver , Last(minSilver[ga])) ;
        }
        return ;
    }
    if (siz[ga] < siz[gb]) swap(ga,gb) ;
    parent[gb] = ga ;
    siz[ga] += siz[gb] ;
    Add(a,d) ;
    Add(b,d) ;
    for (multiset<ll>::iterator it = minSilver[gb].begin() ; it != minSilver[gb].end() ; ++it) {
        minSilver[ga].insert (*it) ;
    }
    minSilver[ga].insert (c) ;
    //minSilver[ga] = max(minSilver[ga] , max(c,minSilver[gb])) ;
//     cerr << "minSilver[" << ga << "] = " << Last(minSilver[ga]) << endl ;
//     cerr << "siz[" << ga << "] = " << siz[ga] << endl ;
    if (siz[ga] == N) {
        mSilver = Last(minSilver[ga]) ;
    }
}

int main() {
    cin >> N >> M >> G >> S ;
    for (int i = 0 ; i < M ; ++i) {
        cin >> e[i].X.X >> e[i].X.Y >> e[i].Y.X >> e[i].Y.Y ; --e[i].X.X , --e[i].X.Y ;
    }
    sort (e,e+M,cmp) ;
    for (int i = 0 ; i < N ; ++i) {
        parent[i] = i ;
        siz[i] = 1 ;
    }
    ll BestAns = INF ;
    for (int i = 0 ; i < M ; ++i) {
//         cerr << e[i].X.X << " " << e[i].X.Y << "   : " << e[i].Y.X << " , " << e[i].Y.Y << endl ;
        Join (e[i].X.X , e[i].X.Y , e[i].Y.Y , i) ;
//         cerr << endl ;
//         cerr << e[i].Y.X*G << " + " << mSilver*S << endl ;
//         cerr << "-------------------------------------------------------------------------" << endl << endl ;
        BestAns = min (BestAns,e[i].Y.X*G+mSilver*S) ;
    }
    cout << ((BestAns<INF)?BestAns:-1) << endl ;
    return 0 ;
}


#include <cstring>
#include <iostream>
#include <vector>
#include <algorithm>
#include <set>
using namespace std ;

const int MAXN = 200 ;
const int MAXM = 50 * 1000 ;

#define pb push_back
#define X first
#define Y second

typedef long long ll ;
typedef pair <ll,ll> pii ;
typedef pair <pii,pii> pipi ;

int N , M ;
int G , S ;

// vector <int> d[MAXN] ;
// vector <int> num[MAXN] ;

int parent[MAXN] ;
int siz[MAXN] ;
ll minSilver[MAXN] ;
ll mSilver = 1000LL * 1000 * 1000 * 1000 ;

pipi e[MAXM] ;
bool cmp (pipi a , pipi b) {
    return a.Y.X < b.Y.X ;
}

struct comp {
    bool operator () (int a , int b) {
        if (e[a].Y.Y != e[b].Y.Y)
            return e[a].Y.Y < e[b].Y.Y ;
        return a < b ;
    }
};

set <int,comp> v[MAXN] ;

ll findpath (ll a) {
    if (a == parent[a]) return a ;
    ll b = findpath (parent[a]) ;
    parent[a] = b ;
    return b ;
}

bool is[MAXN] ;
int dfs (ll a , ll b , ll c) {
    if (is[a]) return -2;
    if (a == b) return -1 ;
    is[a] = true ;
    int ans = -2 , got = -2 ;
    for (set<int,comp>::iterator it = v[a].begin() ; it != v[a].end() ; ++it) {
        int f = *it ;
        int nei = e[f].X.X^e[f].X.Y^a ;
        int DFS = dfs(nei,b,c) ;
        if (DFS == -1) {
            ans = e[f].Y.Y ;
            got = f ;
        }
        if (DFS >= 0) {
            if (e[DFS].Y.Y > ans) {
                ans = e[DFS].Y.Y ;
                got = DFS ;
            }
            if (e[f].Y.Y > ans) {
                ans = e[f].Y.Y ;
                got = f ;
            }
        }
    }
    return got ;
}

void Add (ll a , ll b) {
    //d[a].pb (b) ;
    //num[a].pb (c) ;
    v[a].insert (b) ;
}

void Join (ll a , ll b , ll c, ll d) {
    if (a == b) return ;
    ll ga = findpath(a) ;
    ll gb = findpath(b) ;
    //  cerr << ga << " : " << gb << endl ;
    if (ga == gb) {
        memset (is,false,sizeof(is)) ;
        int ret = dfs (a,b,c) ;
        if (ret >= 0 && e[ret].Y.Y > c) {
//             cerr << a << " " << b << " " << c << " " << d << " : ret = " << ret << endl ;
            v[e[ret].X.X].erase (ret) ;
            v[e[ret].X.Y].erase (ret) ;
            Add (a,d) ;
            Add (b,d) ;
//             cerr << v[a].size() << " , " << v[b].size() << endl ;
            minSilver[ga] += c-e[ret].Y.Y ;
        }
        if (siz[ga] == N)
            mSilver = min (mSilver , minSilver[ga]) ;
        return ;
    }
    if (siz[ga] < siz[gb]) swap(ga,gb) ;
    parent[gb] = ga ;
    siz[ga] += siz[gb] ;
    Add(a,d) ;
    Add(b,d) ;
    minSilver[ga] = max(minSilver[ga] , max(c,minSilver[gb])) ;
//       cerr << "minSilver[" << ga << "] = " << minSilver[ga] << endl ;
//       cerr << "siz[" << ga << "] = " << siz[ga] << endl ;
    if (siz[ga] == N)
        mSilver = minSilver[ga] ;
}

int main() {
    cin >> N >> M >> G >> S ;
    for (int i = 0 ; i < M ; ++i) {
        cin >> e[i].X.X >> e[i].X.Y >> e[i].Y.X >> e[i].Y.Y ; --e[i].X.X , --e[i].X.Y ;
    }
    sort (e,e+M,cmp) ;
    for (int i = 0 ; i < N ; ++i) {
        parent[i] = i ;
        siz[i] = 1 ;
    }
    ll BestAns = 1000LL * 1000 * 1000 * 1000 ;
    for (int i = 0 ; i < M ; ++i) {
//           cerr << e[i].X.X << " " << e[i].X.Y << "   : " << e[i].Y.X << " , " << e[i].Y.Y << endl ;
        Join (e[i].X.X , e[i].X.Y , e[i].Y.Y , i) ;
//           cerr << endl << "-------------------------------------------------------------------------------------------------------------------" << endl << endl << endl;
        BestAns = min (BestAns,e[i].Y.X*G+mSilver*S) ;
    }
    cout << BestAns << endl ;
    return 0 ;
}


#include <cstring>
#include <iostream>
#include <vector>
#include <algorithm>
#include <set>
using namespace std ;

#define pb push_back
#define X first
#define Y second

typedef long long ll ;
typedef pair <ll,ll> pii ;
typedef pair <pii,pii> pipi ;

const ll MAXN = 200 ;
const ll MAXM = 50 * 1000 ;
const ll INF = 1000LL * 1000 * 1000 * 1000  ;

ll N , M ;
ll G , S ;

// vector <ll> d[MAXN] ;
// vector <ll> num[MAXN] ;

ll parent[MAXN] ;
ll siz[MAXN] ;
multiset <ll> minSilver[MAXN] ;
ll mSilver = INF ;

pipi e[MAXM] ;
bool cmp (pipi a , pipi b) {
    return a.Y.X < b.Y.X ;
}

struct comp {
    bool operator () (ll a , ll b) {
        if (e[a].Y.Y != e[b].Y.Y)
            return e[a].Y.Y < e[b].Y.Y ;
        return a < b ;
    }
};

set <ll,comp> v[MAXN] ;

ll findpath (ll a) {
    if (a == parent[a]) return a ;
    ll b = findpath (parent[a]) ;
    parent[a] = b ;
    return b ;
}

bool is[MAXN] ;
ll dfs (ll a , ll b , ll c) {
    if (is[a]) return -2;
    if (a == b) return -1 ;
    is[a] = true ;
    ll ans = -2 , got = -2 ;
    for (set<ll,comp>::iterator it = v[a].begin() ; it != v[a].end() ; ++it) {
        ll f = *it ;
        ll nei = e[f].X.X^e[f].X.Y^a ;
        ll DFS = dfs(nei,b,c) ;
        if (DFS == -1) {
            ans = e[f].Y.Y ;
            got = f ;
        }
        if (DFS >= 0) {
            if (e[DFS].Y.Y > ans) {
                ans = e[DFS].Y.Y ;
                got = DFS ;
            }
            if (e[f].Y.Y > ans) {
                ans = e[f].Y.Y ;
                got = f ;
            }
        }
    }
    return got ;
}

void Add (ll a , ll b) {
    //d[a].pb (b) ;
    //num[a].pb (c) ;
    v[a].insert (b) ;
}

ll Last (multiset <ll> & a) {
    multiset <ll>::iterator it = a.end() ;
    --it ;
    return *it ;
}

void Join (ll a , ll b , ll c, ll d) {
    if (a == b) return ;
    ll ga = findpath(a) ;
    ll gb = findpath(b) ;
//       cerr << ga << " : " << gb << endl ;
    if (ga == gb) {
        memset (is,false,sizeof(is)) ;
        ll ret = dfs (a,b,c) ;
        if (ret >= 0 && e[ret].Y.Y > c) {
//             cerr << a << " " << b << " " << c << " " << d << " : ret = " << ret << endl ;
//             cerr << "e[ret] : " << e[ret].Y.X << " , " << e[ret].Y.Y << endl ;
            v[e[ret].X.X].erase (ret) ;
            v[e[ret].X.Y].erase (ret) ;
            Add (a,d) ;
            Add (b,d) ;
//             cerr << v[a].size() << " , " << v[b].size() << endl ;
//             for (multiset <ll>::iterator it = minSilver[ga].begin() ; it != minSilver[ga].end() ; ++it) {
//                 cerr << *it << " . " ;
//             }
//             cerr << endl ;
            minSilver[ga].erase (minSilver[ga].find(e[ret].Y.Y)) ;
//             cerr << v[a].size() << " , " << v[b].size() << endl ;
//             for (multiset <ll>::iterator it = minSilver[ga].begin() ; it != minSilver[ga].end() ; ++it) {
//                 cerr << *it << " . " ;
//             }
//             cerr << endl ;
            minSilver[ga].insert (c) ;
//             cerr <<"minSilver[ga] = " <<  Last(minSilver[ga]) << endl ;
        }
        if (siz[ga] == N) {
            mSilver = min (mSilver , Last(minSilver[ga])) ;
        }
        return ;
    }
    if (siz[ga] < siz[gb]) swap(ga,gb) ;
    parent[gb] = ga ;
    siz[ga] += siz[gb] ;
    Add(a,d) ;
    Add(b,d) ;
    for (multiset<ll>::iterator it = minSilver[gb].begin() ; it != minSilver[gb].end() ; ++it) {
        minSilver[ga].insert (*it) ;
    }
    minSilver[ga].insert (c) ;
    //minSilver[ga] = max(minSilver[ga] , max(c,minSilver[gb])) ;
//     cerr << "minSilver[" << ga << "] = " << Last(minSilver[ga]) << endl ;
//     cerr << "siz[" << ga << "] = " << siz[ga] << endl ;
    if (siz[ga] == N) {
        mSilver = Last(minSilver[ga]) ;
    }
}

int main() {
    cin >> N >> M >> G >> S ;
    for (ll i = 0 ; i < M ; ++i) {
        cin >> e[i].X.X >> e[i].X.Y >> e[i].Y.X >> e[i].Y.Y ; --e[i].X.X , --e[i].X.Y ;
    }
    sort (e,e+M,cmp) ;
    for (ll i = 0 ; i < N ; ++i) {
        parent[i] = i ;
        siz[i] = 1 ;
    }
    ll BestAns = INF ;
    for (ll i = 0 ; i < M ; ++i) {
//         cerr << e[i].X.X << " " << e[i].X.Y << "   : " << e[i].Y.X << " , " << e[i].Y.Y << endl ;
        Join (e[i].X.X , e[i].X.Y , e[i].Y.Y , i) ;
//         cerr << endl ;
//         cerr << e[i].Y.X*G << " + " << mSilver*S << endl ;
//         cerr << "-------------------------------------------------------------------------" << endl << endl ;
        BestAns = min (BestAns,e[i].Y.X*G+mSilver*S) ;
    }
    cout << ((BestAns<INF)?BestAns:-1) << endl ;
    return 0 ;
}


#include <cstring>
#include <iostream>
#include <vector>
#include <algorithm>
#include <set>
using namespace std ;

const int MAXN = 200 ;
const int MAXM = 50 * 1000 ;

#define pb push_back
#define X first
#define Y second

typedef long long ll ;
typedef pair <ll,ll> pii ;
typedef pair <pii,pii> pipi ;

const ll INF = 1000LL * 1000 * 1000 * 1000 * 1000  ;

int N , M ;
int G , S ;

// vector <int> d[MAXN] ;
// vector <int> num[MAXN] ;

int parent[MAXN] ;
int siz[MAXN] ;
multiset <ll> minSilver[MAXN] ;
ll mSilver = INF ;

pipi e[MAXM] ;
bool cmp (pipi a , pipi b) {
    return a.Y.X < b.Y.X ;
}

struct comp {
    bool operator () (int a , int b) {
        if (e[a].Y.Y != e[b].Y.Y)
            return e[a].Y.Y < e[b].Y.Y ;
        return a < b ;
    }
};

set <int,comp> v[MAXN] ;

ll findpath (ll a) {
    if (a == parent[a]) return a ;
    ll b = findpath (parent[a]) ;
    parent[a] = b ;
    return b ;
}

bool is[MAXN] ;
int dfs (ll a , ll b , ll c) {
    if (is[a]) return -2;
    if (a == b) return -1 ;
    is[a] = true ;
    int ans = -2 , got = -2 ;
    for (set<int,comp>::iterator it = v[a].begin() ; it != v[a].end() ; ++it) {
        int f = *it ;
        int nei = e[f].X.X^e[f].X.Y^a ;
        int DFS = dfs(nei,b,c) ;
        if (DFS == -1) {
            ans = e[f].Y.Y ;
            got = f ;
        }
        if (DFS >= 0) {
            if (e[DFS].Y.Y > ans) {
                ans = e[DFS].Y.Y ;
                got = DFS ;
            }
            if (e[f].Y.Y > ans) {
                ans = e[f].Y.Y ;
                got = f ;
            }
        }
    }
    return got ;
}

void Add (ll a , ll b) {
    //d[a].pb (b) ;
    //num[a].pb (c) ;
    v[a].insert (b) ;
}

ll Last (multiset <ll> & a) {
    multiset <ll>::iterator it = a.end() ;
    --it ;
    return *it ;
}

void Join (ll a , ll b , ll c, ll d) {
    if (a == b) return ;
    ll ga = findpath(a) ;
    ll gb = findpath(b) ;
//       cerr << ga << " : " << gb << endl ;
    if (ga == gb) {
        memset (is,false,sizeof(is)) ;
        int ret = dfs (a,b,c) ;
        if (ret >= 0 && e[ret].Y.Y > c) {
//             cerr << a << " " << b << " " << c << " " << d << " : ret = " << ret << endl ;
//             cerr << "e[ret] : " << e[ret].Y.X << " , " << e[ret].Y.Y << endl ;
            v[e[ret].X.X].erase (ret) ;
            v[e[ret].X.Y].erase (ret) ;
            Add (a,d) ;
            Add (b,d) ;
//             cerr << v[a].size() << " , " << v[b].size() << endl ;

            minSilver[ga].erase (e[ret].Y.Y) ;
            minSilver[ga].insert (c) ;
//             cerr <<"minSilver[ga] = " <<  Last(minSilver[ga]) << endl ;
        }
        if (siz[ga] == N) {
            mSilver = min (mSilver , Last(minSilver[ga])) ;
        }
        return ;
    }
    if (siz[ga] < siz[gb]) swap(ga,gb) ;
    parent[gb] = ga ;
    siz[ga] += siz[gb] ;
    Add(a,d) ;
    Add(b,d) ;
    for (multiset<ll>::iterator it = minSilver[gb].begin() ; it != minSilver[gb].end() ; ++it) {
        minSilver[ga].insert (*it) ;
    }
    minSilver[ga].insert (c) ;
    //minSilver[ga] = max(minSilver[ga] , max(c,minSilver[gb])) ;
//     cerr << "minSilver[" << ga << "] = " << Last(minSilver[ga]) << endl ;
//     cerr << "siz[" << ga << "] = " << siz[ga] << endl ;
    if (siz[ga] == N) {
        mSilver = Last(minSilver[ga]) ;
    }
}

int main() {
    cin >> N >> M >> G >> S ;
    for (int i = 0 ; i < M ; ++i) {
        cin >> e[i].X.X >> e[i].X.Y >> e[i].Y.X >> e[i].Y.Y ; --e[i].X.X , --e[i].X.Y ;
    }
    sort (e,e+M,cmp) ;
    for (int i = 0 ; i < N ; ++i) {
        parent[i] = i ;
        siz[i] = 1 ;
    }
    ll BestAns = INF ;
    for (int i = 0 ; i < M ; ++i) {
//         cerr << e[i].X.X << " " << e[i].X.Y << "   : " << e[i].Y.X << " , " << e[i].Y.Y << endl ;
        Join (e[i].X.X , e[i].X.Y , e[i].Y.Y , i) ;
//         cerr << endl ;
//         cerr << e[i].Y.X*G << " + " << mSilver*S << endl ;
//         cerr << "-------------------------------------------------------------------------" << endl << endl ;
        BestAns = min (BestAns,e[i].Y.X*G+mSilver*S) ;
    }
    cout << ((BestAns<INF)?BestAns:-1) << endl ;
    return 0 ;
}


#include <cstring>
#include <iostream>
#include <vector>
#include <algorithm>
#include <set>
using namespace std ;

const int MAXN = 200 ;
const int MAXM = 50 * 1000 ;

#define pb push_back
#define X first
#define Y second

typedef long long ll ;
typedef pair <ll,ll> pii ;
typedef pair <pii,pii> pipi ;

const ll INF = 1000LL * 1000 * 1000 * 1000 * 1000  ;

int N , M ;
ll G , S ;

// vector <int> d[MAXN] ;
// vector <int> num[MAXN] ;

int parent[MAXN] ;
int siz[MAXN] ;
multiset <ll> minSilver[MAXN] ;
ll mSilver = INF ;

pipi e[MAXM] ;
bool cmp (pipi a , pipi b) {
    return a.Y.X < b.Y.X ;
}

struct comp {
    bool operator () (ll a , ll b) {
        if (e[a].Y.Y != e[b].Y.Y)
            return e[a].Y.Y < e[b].Y.Y ;
        return a < b ;
    }
};

set <ll,comp> v[MAXN] ;

ll findpath (ll a) {
    if (a == parent[a]) return a ;
    ll b = findpath (parent[a]) ;
    parent[a] = b ;
    return b ;
}

bool is[MAXN] ;
ll dfs (ll a , ll b , ll c) {
    if (is[a]) return -2;
    if (a == b) return -1 ;
    is[a] = true ;
    ll ans = -2 , got = -2 ;
    for (set<ll,comp>::iterator it = v[a].begin() ; it != v[a].end() ; ++it) {
        ll f = *it ;
        ll nei = e[f].X.X^e[f].X.Y^a ;
        ll DFS = dfs(nei,b,c) ;
        if (DFS == -1) {
            ans = e[f].Y.Y ;
            got = f ;
        }
        if (DFS >= 0) {
            if (e[DFS].Y.Y > ans) {
                ans = e[DFS].Y.Y ;
                got = DFS ;
            }
            if (e[f].Y.Y > ans) {
                ans = e[f].Y.Y ;
                got = f ;
            }
        }
    }
    return got ;
}

void Add (ll a , ll b) {
    //d[a].pb (b) ;
    //num[a].pb (c) ;
    v[a].insert (b) ;
}

ll Last (multiset <ll> & a) {
    multiset <ll>::iterator it = a.end() ;
    --it ;
    return *it ;
}

void Join (ll a , ll b , ll c, ll d) {
    if (a == b) return ;
    ll ga = findpath(a) ;
    ll gb = findpath(b) ;
//       cerr << ga << " : " << gb << endl ;
    if (ga == gb) {
        memset (is,false,sizeof(is)) ;
        ll ret = dfs (a,b,c) ;
        if (ret >= 0 && e[ret].Y.Y > c) {
//             cerr << a << " " << b << " " << c << " " << d << " : ret = " << ret << endl ;
//             cerr << "e[ret] : " << e[ret].Y.X << " , " << e[ret].Y.Y << endl ;
            v[e[ret].X.X].erase (ret) ;
            v[e[ret].X.Y].erase (ret) ;
            Add (a,d) ;
            Add (b,d) ;
//             cerr << v[a].size() << " , " << v[b].size() << endl ;
//             for (multiset <ll>::iterator it = minSilver[ga].begin() ; it != minSilver[ga].end() ; ++it) {
//                 cerr << *it << " . " ;
//             }
//             cerr << endl ;
            minSilver[ga].erase (minSilver[ga].find(e[ret].Y.Y)) ;
//             cerr << v[a].size() << " , " << v[b].size() << endl ;
//             for (multiset <ll>::iterator it = minSilver[ga].begin() ; it != minSilver[ga].end() ; ++it) {
//                 cerr << *it << " . " ;
//             }
//             cerr << endl ;
            minSilver[ga].insert (c) ;
//             cerr <<"minSilver[ga] = " <<  Last(minSilver[ga]) << endl ;
        }
        if (siz[ga] == N) {
            mSilver = min (mSilver , Last(minSilver[ga])) ;
        }
        return ;
    }
    if (siz[ga] < siz[gb]) swap(ga,gb) ;
    parent[gb] = ga ;
    siz[ga] += siz[gb] ;
    Add(a,d) ;
    Add(b,d) ;
    for (multiset<ll>::iterator it = minSilver[gb].begin() ; it != minSilver[gb].end() ; ++it) {
        minSilver[ga].insert (*it) ;
    }
    minSilver[ga].insert (c) ;
    //minSilver[ga] = max(minSilver[ga] , max(c,minSilver[gb])) ;
//     cerr << "minSilver[" << ga << "] = " << Last(minSilver[ga]) << endl ;
//     cerr << "siz[" << ga << "] = " << siz[ga] << endl ;
    if (siz[ga] == N) {
        mSilver = Last(minSilver[ga]) ;
    }
}

int main() {
    cin >> N >> M >> G >> S ;
    for (int i = 0 ; i < M ; ++i) {
        cin >> e[i].X.X >> e[i].X.Y >> e[i].Y.X >> e[i].Y.Y ; --e[i].X.X , --e[i].X.Y ;
    }
    sort (e,e+M,cmp) ;
    for (int i = 0 ; i < N ; ++i) {
        parent[i] = i ;
        siz[i] = 1 ;
    }
    ll BestAns = INF ;
    for (int i = 0 ; i < M ; ++i) {
//         cerr << e[i].X.X << " " << e[i].X.Y << "   : " << e[i].Y.X << " , " << e[i].Y.Y << endl ;
        Join (e[i].X.X , e[i].X.Y , e[i].Y.Y , i) ;
//         cerr << endl ;
//         cerr << e[i].Y.X*G << " + " << mSilver*S << endl ;
//         cerr << "-------------------------------------------------------------------------" << endl << endl ;
        BestAns = min (BestAns,e[i].Y.X*G+mSilver*S) ;
    }
    cout << ((BestAns<INF)?BestAns:-1) << endl ;
    return 0 ;
}


#include <cstring>
#include <iostream>
#include <vector>
#include <algorithm>
#include <set>
using namespace std ;

const int MAXN = 200 ;
const int MAXM = 50 * 1000 ;

#define pb push_back
#define X first
#define Y second

typedef long long ll ;
typedef pair <ll,ll> pii ;
typedef pair <pii,pii> pipi ;

int N , M ;
int G , S ;

// vector <int> d[MAXN] ;
// vector <int> num[MAXN] ;

set <int> v[MAXN] ;

int parent[MAXN] ;
int siz[MAXN] ;
ll minSilver[MAXN] ;
ll mSilver = 1000LL * 1000 * 1000 * 1000 ;

pipi e[MAXM] ;
bool cmp (pipi a , pipi b) {
    return a.Y.X < b.Y.X ;
}

ll findpath (ll a) {
    if (a == parent[a]) return a ;
    ll b = findpath (parent[a]) ;
    parent[a] = b ;
    return b ;
}

bool is[MAXN] ;
int dfs (ll a , ll b , ll c) {
    if (is[a]) return -1;
    if (a == b) return 0 ;
    is[a] = true ;
    int ans = -1 , got = -1 ;
    for (set<int>::iterator it = v[a].begin() ; it != v[a].end() ; ++it) {
        int f = *it ;
        int nei = e[f].X.X^e[f].X.Y^a ;
        int DFS = dfs(nei,b,c) ;
        if (DFS != -1) {
            if (e[DFS].Y.Y > ans) {
                ans = e[DFS].Y.Y ;
                got = DFS ;
            }
            if (e[f].Y.Y > ans) {
                ans = e[f].Y.Y ;
                got = f ;
            }
        }
    }
    return got ;
}

void Add (ll a , ll b) {
    //d[a].pb (b) ;
    //num[a].pb (c) ;
    v[a].insert (b) ;
}

void Join (ll a , ll b , ll c, ll d) {
    if (a == b) return ;
    ll ga = findpath(a) ;
    ll gb = findpath(b) ;
//     cerr << ga << " : " << gb << endl ;
    if (ga == gb) {
        memset (is,false,sizeof(is)) ;
        int ret = dfs (a,b,c) ;
        if (ret != -1 && e[ret].Y.Y > c) {
//             cerr << a << " " << b << " " << c << " " << d << endl ;
            v[e[ret].X.X].erase (ret) ;
            v[e[ret].X.Y].erase (ret) ;
            Add (a,d) ;
            Add (b,d) ;
            minSilver[ga] += c-e[ret].Y.Y ;
        }
        if (siz[ga] == N)
            mSilver = min (mSilver , minSilver[ga]) ;
        return ;
    }
    if (siz[ga] < siz[gb]) swap(ga,gb) ;
    parent[gb] = ga ;
    siz[ga] += siz[gb] ;
    Add(a,d) ;
    Add(b,d) ;
    minSilver[ga] = max(minSilver[ga] , max(c,minSilver[gb])) ;
//     cerr << "minSilver[" << ga << "] = " << minSilver[ga] << endl ;
//     cerr << "siz[" << ga << "] = " << siz[ga] << endl ;
    if (siz[ga] == N)
        mSilver = minSilver[ga] ;
}

int main() {
    cin >> N >> M >> G >> S ;
    for (int i = 0 ; i < M ; ++i) {
        cin >> e[i].X.X >> e[i].X.Y >> e[i].Y.X >> e[i].Y.Y ; --e[i].X.X , --e[i].X.Y ;
    }
    sort (e,e+M,cmp) ;
    for (int i = 0 ; i < N ; ++i) {
        parent[i] = i ;
        siz[i] = 1 ;
    }
    ll BestAns = 1000LL * 1000 * 1000 * 1000 ;
    for (int i = 0 ; i < M ; ++i) {
//         cerr << e[i].X.X << " " << e[i].X.Y << "   : " << e[i].Y.X << " , " << e[i].Y.Y << endl ;
        Join (e[i].X.X , e[i].X.Y , e[i].Y.Y , i) ;
//         cerr << endl << "-------------------------------------------------------------------------------------------------------------------" << endl << endl << endl;
        BestAns = min (BestAns,e[i].Y.X*G+mSilver*S) ;
    }
    cout << BestAns << endl ;
    return 0 ;
}


#include <cstring>
#include <iostream>
#include <vector>
#include <algorithm>
#include <set>
using namespace std ;

#define pb push_back
#define X first
#define Y second

typedef long long ll ;
typedef pair <ll,ll> pii ;
typedef pair <pii,pii> pipi ;

const ll MAXN = 200 ;
const ll MAXM = 50 * 1000 ;

ll N , M ;
ll G , S ;

// vector <ll> d[MAXN] ;
// vector <ll> num[MAXN] ;

ll parent[MAXN] ;
ll siz[MAXN] ;
multiset <ll> minSilver[MAXN] ;
ll mSilver ;
bool haveANS ;

pipi e[MAXM] ;
bool cmp (pipi a , pipi b) {
    return a.Y.X < b.Y.X ;
}

struct comp {
    bool operator () (ll a , ll b) {
        if (e[a].Y.Y != e[b].Y.Y)
            return e[a].Y.Y < e[b].Y.Y ;
        return a < b ;
    }
};

set <ll,comp> v[MAXN] ;

ll findpath (ll a) {
    if (a == parent[a]) return a ;
    ll b = findpath (parent[a]) ;
    parent[a] = b ;
    return b ;
}

bool is[MAXN] ;
ll dfs (ll a , ll b , ll c) {
    if (is[a]) return -2;
    if (a == b) return -1 ;
    is[a] = true ;
    ll ans = -2 , got = -2 ;
    for (set<ll,comp>::iterator it = v[a].begin() ; it != v[a].end() ; ++it) {
        ll f = *it ;
        ll nei = e[f].X.X^e[f].X.Y^a ;
        ll DFS = dfs(nei,b,c) ;
        if (DFS == -1) {
            ans = e[f].Y.Y ;
            got = f ;
        }
        if (DFS >= 0) {
            if (e[DFS].Y.Y > ans) {
                ans = e[DFS].Y.Y ;
                got = DFS ;
            }
            if (e[f].Y.Y > ans) {
                ans = e[f].Y.Y ;
                got = f ;
            }
        }
    }
    return got ;
}

void Add (ll a , ll b) {
    //d[a].pb (b) ;
    //num[a].pb (c) ;
    v[a].insert (b) ;
}

ll Last (multiset <ll> & a) {
    multiset <ll>::iterator it = a.end() ;
    --it ;
    return *it ;
}

void Join (ll a , ll b , ll c, ll d) {
    if (a == b) return ;
    ll ga = findpath(a) ;
    ll gb = findpath(b) ;
//       cerr << ga << " : " << gb << endl ;
    if (ga == gb) {
        memset (is,false,sizeof(is)) ;
        ll ret = dfs (a,b,c) ;
        if (ret >= 0 && e[ret].Y.Y > c) {
//             cerr << a << " " << b << " " << c << " " << d << " : ret = " << ret << endl ;
//             cerr << "e[ret] : " << e[ret].Y.X << " , " << e[ret].Y.Y << endl ;
            v[e[ret].X.X].erase (ret) ;
            v[e[ret].X.Y].erase (ret) ;
            Add (a,d) ;
            Add (b,d) ;
//             cerr << v[a].size() << " , " << v[b].size() << endl ;
//             for (multiset <ll>::iterator it = minSilver[ga].begin() ; it != minSilver[ga].end() ; ++it) {
//                 cerr << *it << " . " ;
//             }
//             cerr << endl ;
            minSilver[ga].erase (minSilver[ga].find(e[ret].Y.Y)) ;
//             cerr << v[a].size() << " , " << v[b].size() << endl ;
//             for (multiset <ll>::iterator it = minSilver[ga].begin() ; it != minSilver[ga].end() ; ++it) {
//                 cerr << *it << " . " ;
//             }
//             cerr << endl ;
            minSilver[ga].insert (c) ;
//             cerr <<"minSilver[ga] = " <<  Last(minSilver[ga]) << endl ;
        }
        if (siz[ga] == N) {
            mSilver = min (mSilver , Last(minSilver[ga])) ;
        }
        return ;
    }
    if (siz[ga] < siz[gb]) swap(ga,gb) ;
    parent[gb] = ga ;
    siz[ga] += siz[gb] ;
    Add(a,d) ;
    Add(b,d) ;
    for (multiset<ll>::iterator it = minSilver[gb].begin() ; it != minSilver[gb].end() ; ++it) {
        minSilver[ga].insert (*it) ;
    }
    minSilver[ga].insert (c) ;
    //minSilver[ga] = max(minSilver[ga] , max(c,minSilver[gb])) ;
//     cerr << "minSilver[" << ga << "] = " << Last(minSilver[ga]) << endl ;
//     cerr << "siz[" << ga << "] = " << siz[ga] << endl ;
    if (siz[ga] == N) {
        haveANS = true ;
        mSilver = Last(minSilver[ga]) ;
    }
}

int main() {
    cin >> N >> M >> G >> S ;
    for (ll i = 0 ; i < M ; ++i) {
        cin >> e[i].X.X >> e[i].X.Y >> e[i].Y.X >> e[i].Y.Y ; --e[i].X.X , --e[i].X.Y ;
    }
    sort (e,e+M,cmp) ;
    for (ll i = 0 ; i < N ; ++i) {
        parent[i] = i ;
        siz[i] = 1 ;
    }
    ll BestAns = -1 ;
    for (ll i = 0 ; i < M ; ++i) {
//         cerr << e[i].X.X << " " << e[i].X.Y << "   : " << e[i].Y.X << " , " << e[i].Y.Y << endl ;
        Join (e[i].X.X , e[i].X.Y , e[i].Y.Y , i) ;
//         cerr << endl ;
//         cerr << e[i].Y.X*G << " + " << mSilver*S << endl ;
//         cerr << "-------------------------------------------------------------------------" << endl << endl ;
        if (haveANS) {
            ll d = e[i].Y.X*G+mSilver*S ;
            if (BestAns == -1 || d < BestAns)
                BestAns = d ;
        }
    }
    cout << BestAns << endl ;
    return 0 ;
}


#include <cstring>
#include <iostream>
#include <vector>
#include <algorithm>
#include <set>
using namespace std ;

#define pb push_back
#define X first
#define Y second

typedef long long ll ;
typedef pair <ll,ll> pii ;
typedef pair <pii,pii> pipi ;

const ll MAXN = 200 ;
const ll MAXM = 50 * 1000 ;
const ll INF = 1000LL * 1000 * 1000 * 1000 * 1000 * 1000  ;

ll N , M ;
ll G , S ;

// vector <ll> d[MAXN] ;
// vector <ll> num[MAXN] ;

ll parent[MAXN] ;
ll siz[MAXN] ;
multiset <ll> minSilver[MAXN] ;
ll mSilver = INF ;

pipi e[MAXM] ;
bool cmp (pipi a , pipi b) {
    return a.Y.X < b.Y.X ;
}

struct comp {
    bool operator () (ll a , ll b) {
        if (e[a].Y.Y != e[b].Y.Y)
            return e[a].Y.Y < e[b].Y.Y ;
        return a < b ;
    }
};

set <ll,comp> v[MAXN] ;

ll findpath (ll a) {
    if (a == parent[a]) return a ;
    ll b = findpath (parent[a]) ;
    parent[a] = b ;
    return b ;
}

bool is[MAXN] ;
ll dfs (ll a , ll b , ll c) {
    if (is[a]) return -2;
    if (a == b) return -1 ;
    is[a] = true ;
    ll ans = -2 , got = -2 ;
    for (set<ll,comp>::iterator it = v[a].begin() ; it != v[a].end() ; ++it) {
        ll f = *it ;
        ll nei = e[f].X.X^e[f].X.Y^a ;
        ll DFS = dfs(nei,b,c) ;
        if (DFS == -1) {
            ans = e[f].Y.Y ;
            got = f ;
        }
        if (DFS >= 0) {
            if (e[DFS].Y.Y > ans) {
                ans = e[DFS].Y.Y ;
                got = DFS ;
            }
            if (e[f].Y.Y > ans) {
                ans = e[f].Y.Y ;
                got = f ;
            }
        }
    }
    return got ;
}

void Add (ll a , ll b) {
    //d[a].pb (b) ;
    //num[a].pb (c) ;
    v[a].insert (b) ;
}

ll Last (multiset <ll> & a) {
    multiset <ll>::iterator it = a.end() ;
    --it ;
    return *it ;
}

void Join (ll a , ll b , ll c, ll d) {
    if (a == b) return ;
    ll ga = findpath(a) ;
    ll gb = findpath(b) ;
//       cerr << ga << " : " << gb << endl ;
    if (ga == gb) {
        memset (is,false,sizeof(is)) ;
        ll ret = dfs (a,b,c) ;
        if (ret >= 0 && e[ret].Y.Y > c) {
//             cerr << a << " " << b << " " << c << " " << d << " : ret = " << ret << endl ;
//             cerr << "e[ret] : " << e[ret].Y.X << " , " << e[ret].Y.Y << endl ;
            v[e[ret].X.X].erase (ret) ;
            v[e[ret].X.Y].erase (ret) ;
            Add (a,d) ;
            Add (b,d) ;
//             cerr << v[a].size() << " , " << v[b].size() << endl ;
//             for (multiset <ll>::iterator it = minSilver[ga].begin() ; it != minSilver[ga].end() ; ++it) {
//                 cerr << *it << " . " ;
//             }
//             cerr << endl ;
            minSilver[ga].erase (minSilver[ga].find(e[ret].Y.Y)) ;
//             cerr << v[a].size() << " , " << v[b].size() << endl ;
//             for (multiset <ll>::iterator it = minSilver[ga].begin() ; it != minSilver[ga].end() ; ++it) {
//                 cerr << *it << " . " ;
//             }
//             cerr << endl ;
            minSilver[ga].insert (c) ;
//             cerr <<"minSilver[ga] = " <<  Last(minSilver[ga]) << endl ;
        }
        if (siz[ga] == N) {
            mSilver = min (mSilver , Last(minSilver[ga])) ;
        }
        return ;
    }
    if (siz[ga] < siz[gb]) swap(ga,gb) ;
    parent[gb] = ga ;
    siz[ga] += siz[gb] ;
    Add(a,d) ;
    Add(b,d) ;
    for (multiset<ll>::iterator it = minSilver[gb].begin() ; it != minSilver[gb].end() ; ++it) {
        minSilver[ga].insert (*it) ;
    }
    minSilver[ga].insert (c) ;
    //minSilver[ga] = max(minSilver[ga] , max(c,minSilver[gb])) ;
//     cerr << "minSilver[" << ga << "] = " << Last(minSilver[ga]) << endl ;
//     cerr << "siz[" << ga << "] = " << siz[ga] << endl ;
    if (siz[ga] == N) {
        mSilver = Last(minSilver[ga]) ;
    }
}

int main() {
    cin >> N >> M >> G >> S ;
    for (ll i = 0 ; i < M ; ++i) {
        cin >> e[i].X.X >> e[i].X.Y >> e[i].Y.X >> e[i].Y.Y ; --e[i].X.X , --e[i].X.Y ;
    }
    sort (e,e+M,cmp) ;
    for (ll i = 0 ; i < N ; ++i) {
        parent[i] = i ;
        siz[i] = 1 ;
    }
    ll BestAns = INF ;
    for (ll i = 0 ; i < M ; ++i) {
//         cerr << e[i].X.X << " " << e[i].X.Y << "   : " << e[i].Y.X << " , " << e[i].Y.Y << endl ;
        Join (e[i].X.X , e[i].X.Y , e[i].Y.Y , i) ;
//         cerr << endl ;
//         cerr << e[i].Y.X*G << " + " << mSilver*S << endl ;
//         cerr << "-------------------------------------------------------------------------" << endl << endl ;
        BestAns = min (BestAns,e[i].Y.X*G+mSilver*S) ;
    }
    cout << ((BestAns<INF)?BestAns:-1) << endl ;
    return 0 ;
}


#include <cstring>
#include <iostream>
#include <vector>
#include <algorithm>
#include <set>
using namespace std ;

#define pb push_back
#define X first
#define Y second

typedef long long ll ;
typedef pair <ll,ll> pii ;
typedef pair <pii,pii> pipi ;

const ll MAXN = 200 ;
const ll MAXM = 50 * 1000 ;
const ll INF = 1000LL * 1000 * 1000 * 1000 * 1000 * 100  ;

ll N , M ;
ll G , S ;

// vector <ll> d[MAXN] ;
// vector <ll> num[MAXN] ;

ll parent[MAXN] ;
ll siz[MAXN] ;
multiset <ll> minSilver[MAXN] ;
ll mSilver = INF ;

pipi e[MAXM] ;
bool cmp (pipi a , pipi b) {
    return a.Y.X < b.Y.X ;
}

struct comp {
    bool operator () (ll a , ll b) {
        if (e[a].Y.Y != e[b].Y.Y)
            return e[a].Y.Y < e[b].Y.Y ;
        return a < b ;
    }
};

set <ll,comp> v[MAXN] ;

ll findpath (ll a) {
    if (a == parent[a]) return a ;
    ll b = findpath (parent[a]) ;
    parent[a] = b ;
    return b ;
}

bool is[MAXN] ;
ll dfs (ll a , ll b , ll c) {
    if (is[a]) return -2;
    if (a == b) return -1 ;
    is[a] = true ;
    ll ans = -2 , got = -2 ;
    for (set<ll,comp>::iterator it = v[a].begin() ; it != v[a].end() ; ++it) {
        ll f = *it ;
        ll nei = e[f].X.X^e[f].X.Y^a ;
        ll DFS = dfs(nei,b,c) ;
        if (DFS == -1) {
            ans = e[f].Y.Y ;
            got = f ;
        }
        if (DFS >= 0) {
            if (e[DFS].Y.Y > ans) {
                ans = e[DFS].Y.Y ;
                got = DFS ;
            }
            if (e[f].Y.Y > ans) {
                ans = e[f].Y.Y ;
                got = f ;
            }
        }
    }
    return got ;
}

void Add (ll a , ll b) {
    //d[a].pb (b) ;
    //num[a].pb (c) ;
    v[a].insert (b) ;
}

ll Last (multiset <ll> & a) {
    multiset <ll>::iterator it = a.end() ;
    --it ;
    return *it ;
}

void Join (ll a , ll b , ll c, ll d) {
    if (a == b) return ;
    ll ga = findpath(a) ;
    ll gb = findpath(b) ;
//       cerr << ga << " : " << gb << endl ;
    if (ga == gb) {
        memset (is,false,sizeof(is)) ;
        ll ret = dfs (a,b,c) ;
        if (ret >= 0 && e[ret].Y.Y > c) {
//             cerr << a << " " << b << " " << c << " " << d << " : ret = " << ret << endl ;
//             cerr << "e[ret] : " << e[ret].Y.X << " , " << e[ret].Y.Y << endl ;
            v[e[ret].X.X].erase (ret) ;
            v[e[ret].X.Y].erase (ret) ;
            Add (a,d) ;
            Add (b,d) ;
//             cerr << v[a].size() << " , " << v[b].size() << endl ;
//             for (multiset <ll>::iterator it = minSilver[ga].begin() ; it != minSilver[ga].end() ; ++it) {
//                 cerr << *it << " . " ;
//             }
//             cerr << endl ;
            minSilver[ga].erase (minSilver[ga].find(e[ret].Y.Y)) ;
//             cerr << v[a].size() << " , " << v[b].size() << endl ;
//             for (multiset <ll>::iterator it = minSilver[ga].begin() ; it != minSilver[ga].end() ; ++it) {
//                 cerr << *it << " . " ;
//             }
//             cerr << endl ;
            minSilver[ga].insert (c) ;
//             cerr <<"minSilver[ga] = " <<  Last(minSilver[ga]) << endl ;
        }
        if (siz[ga] == N) {
            mSilver = min (mSilver , Last(minSilver[ga])) ;
        }
        return ;
    }
    if (siz[ga] < siz[gb]) swap(ga,gb) ;
    parent[gb] = ga ;
    siz[ga] += siz[gb] ;
    Add(a,d) ;
    Add(b,d) ;
    for (multiset<ll>::iterator it = minSilver[gb].begin() ; it != minSilver[gb].end() ; ++it) {
        minSilver[ga].insert (*it) ;
    }
    minSilver[ga].insert (c) ;
    //minSilver[ga] = max(minSilver[ga] , max(c,minSilver[gb])) ;
//     cerr << "minSilver[" << ga << "] = " << Last(minSilver[ga]) << endl ;
//     cerr << "siz[" << ga << "] = " << siz[ga] << endl ;
    if (siz[ga] == N) {
        mSilver = Last(minSilver[ga]) ;
    }
}

int main() {
    cin >> N >> M >> G >> S ;
    for (ll i = 0 ; i < M ; ++i) {
        cin >> e[i].X.X >> e[i].X.Y >> e[i].Y.X >> e[i].Y.Y ; --e[i].X.X , --e[i].X.Y ;
    }
    sort (e,e+M,cmp) ;
    for (ll i = 0 ; i < N ; ++i) {
        parent[i] = i ;
        siz[i] = 1 ;
    }
    ll BestAns = INF ;
    for (ll i = 0 ; i < M ; ++i) {
//         cerr << e[i].X.X << " " << e[i].X.Y << "   : " << e[i].Y.X << " , " << e[i].Y.Y << endl ;
        Join (e[i].X.X , e[i].X.Y , e[i].Y.Y , i) ;
//         cerr << endl ;
//         cerr << e[i].Y.X*G << " + " << mSilver*S << endl ;
//         cerr << "-------------------------------------------------------------------------" << endl << endl ;
        BestAns = min (BestAns,e[i].Y.X*G+mSilver*S) ;
    }
    cout << ((BestAns<INF)?BestAns:-1) << endl ;
    return 0 ;
}


#include <cstring>
#include <iostream>
#include <vector>
#include <algorithm>
#include <set>
using namespace std ;

const int MAXN = 200 ;
const int MAXM = 50 * 1000 ;

#define pb push_back
#define X first
#define Y second

typedef long long ll ;
typedef pair <ll,ll> pii ;
typedef pair <pii,pii> pipi ;

const ll INF = 1000LL * 1000 * 1000 * 1000 * 1000 * 1000 ;

int N , M ;
int G , S ;

// vector <int> d[MAXN] ;
// vector <int> num[MAXN] ;

int parent[MAXN] ;
int siz[MAXN] ;
ll minSilver[MAXN] ;
ll mSilver = INF ;

pipi e[MAXM] ;
bool cmp (pipi a , pipi b) {
    return a.Y.X < b.Y.X ;
}

struct comp {
    bool operator () (int a , int b) {
        if (e[a].Y.Y != e[b].Y.Y)
            return e[a].Y.Y < e[b].Y.Y ;
        return a < b ;
    }
};

set <int,comp> v[MAXN] ;

ll findpath (ll a) {
    if (a == parent[a]) return a ;
    ll b = findpath (parent[a]) ;
    parent[a] = b ;
    return b ;
}

bool is[MAXN] ;
int dfs (ll a , ll b , ll c) {
    if (is[a]) return -2;
    if (a == b) return -1 ;
    is[a] = true ;
    int ans = -2 , got = -2 ;
    for (set<int,comp>::iterator it = v[a].begin() ; it != v[a].end() ; ++it) {
        int f = *it ;
        int nei = e[f].X.X^e[f].X.Y^a ;
        int DFS = dfs(nei,b,c) ;
        if (DFS == -1) {
            ans = e[f].Y.Y ;
            got = f ;
        }
        if (DFS >= 0) {
            if (e[DFS].Y.Y > ans) {
                ans = e[DFS].Y.Y ;
                got = DFS ;
            }
            if (e[f].Y.Y > ans) {
                ans = e[f].Y.Y ;
                got = f ;
            }
        }
    }
    return got ;
}

void Add (ll a , ll b) {
    //d[a].pb (b) ;
    //num[a].pb (c) ;
    v[a].insert (b) ;
}

void Join (ll a , ll b , ll c, ll d) {
    if (a == b) return ;
    ll ga = findpath(a) ;
    ll gb = findpath(b) ;
    //  cerr << ga << " : " << gb << endl ;
    if (ga == gb) {
        memset (is,false,sizeof(is)) ;
        int ret = dfs (a,b,c) ;
        if (ret >= 0 && e[ret].Y.Y > c) {
//             cerr << a << " " << b << " " << c << " " << d << " : ret = " << ret << endl ;
            v[e[ret].X.X].erase (ret) ;
            v[e[ret].X.Y].erase (ret) ;
            Add (a,d) ;
            Add (b,d) ;
//             cerr << v[a].size() << " , " << v[b].size() << endl ;
            minSilver[ga] += c-e[ret].Y.Y ;
        }
        if (siz[ga] == N)
            mSilver = min (mSilver , minSilver[ga]) ;
        return ;
    }
    if (siz[ga] < siz[gb]) swap(ga,gb) ;
    parent[gb] = ga ;
    siz[ga] += siz[gb] ;
    Add(a,d) ;
    Add(b,d) ;
    minSilver[ga] = max(minSilver[ga] , max(c,minSilver[gb])) ;
//       cerr << "minSilver[" << ga << "] = " << minSilver[ga] << endl ;
//       cerr << "siz[" << ga << "] = " << siz[ga] << endl ;
    if (siz[ga] == N)
        mSilver = minSilver[ga] ;
}

int main() {
    cin >> N >> M >> G >> S ;
    for (int i = 0 ; i < M ; ++i) {
        cin >> e[i].X.X >> e[i].X.Y >> e[i].Y.X >> e[i].Y.Y ; --e[i].X.X , --e[i].X.Y ;
    }
    sort (e,e+M,cmp) ;
    for (int i = 0 ; i < N ; ++i) {
        parent[i] = i ;
        siz[i] = 1 ;
    }
    ll BestAns = INF ;
    for (int i = 0 ; i < M ; ++i) {
//           cerr << e[i].X.X << " " << e[i].X.Y << "   : " << e[i].Y.X << " , " << e[i].Y.Y << endl ;
        Join (e[i].X.X , e[i].X.Y , e[i].Y.Y , i) ;
//           cerr << endl << "-------------------------------------------------------------------------------------------------------------------" << endl << endl << endl;
        BestAns = min (BestAns,e[i].Y.X*G+mSilver*S) ;
    }
    cout << ((BestAns<INF)?BestAns:-1) << endl ;
    return 0 ;
}


#include <cstring>
#include <iostream>
#include <vector>
#include <algorithm>
#include <set>
using namespace std ;

const int MAXN = 200 ;
const int MAXM = 50 * 1000 ;

#define pb push_back
#define X first
#define Y second

typedef long long ll ;
typedef pair <ll,ll> pii ;
typedef pair <pii,pii> pipi ;

int N , M ;
int G , S ;

// vector <int> d[MAXN] ;
// vector <int> num[MAXN] ;

set <int> v[MAXN] ;

int parent[MAXN] ;
int siz[MAXN] ;
ll minSilver[MAXN] ;
ll mSilver = 1000LL * 1000 * 1000 * 1000 ;

pipi e[MAXM] ;
bool cmp (pipi a , pipi b) {
    return a.Y.X < b.Y.X ;
}

ll findpath (ll a) {
    if (a == parent[a]) return a ;
    ll b = findpath (parent[a]) ;
    parent[a] = b ;
    return b ;
}

bool is[MAXN] ;
int dfs (ll a , ll b , ll c) {
    if (is[a]) return -1;
    if (a == b) return 0 ;
    is[a] = true ;
    int ans = -1 , got = -1 ;
    for (set<int>::iterator it = v[a].begin() ; it != v[a].end() ; ++it) {
        int f = *it ;
        int nei = e[f].X.X^e[f].X.Y^a ;
        int DFS = dfs(nei,b,c) ;
        if (DFS != -1) {
            if (e[DFS].Y.Y > ans) {
                ans = e[DFS].Y.Y ;
                got = DFS ;
            }
            if (e[f].Y.Y > ans) {
                ans = e[f].Y.Y ;
                got = f ;
            }
        }
    }
    return got ;
}

void Add (ll a , ll b) {
    //d[a].pb (b) ;
    //num[a].pb (c) ;
    v[a].insert (b) ;
}

void Join (ll a , ll b , ll c, ll d) {
    ll ga = findpath(a) ;
    ll gb = findpath(b) ;
//     cerr << ga << " : " << gb << endl ;
    if (ga == gb) {
        memset (is,false,sizeof(is)) ;
        int ret = dfs (a,b,c) ;
        if (ret != -1 && e[ret].Y.Y > c) {
            v[e[ret].X.X].erase (ret) ;
            v[e[ret].X.Y].erase (ret) ;
            Add (a,d) ;
            Add (b,d) ;
            minSilver[ga] += c-e[ret].Y.Y ;
        }
        if (siz[ga] == N)
            mSilver = min (mSilver , minSilver[ga]) ;
        return ;
    }
    if (siz[ga] < siz[gb]) swap(ga,gb) ;
    parent[gb] = ga ;
    siz[ga] += siz[gb] ;
    Add(a,d) ;
    Add(b,d) ;
    minSilver[ga] = max(minSilver[ga] , max(c,minSilver[gb])) ;
//     cerr << "minSilver[" << ga << "] = " << minSilver[ga] << endl ;
//     cerr << "siz[" << ga << "] = " << siz[ga] << endl ;
    if (siz[ga] == N)
        mSilver = minSilver[ga] ;
}

int main() {
    cin >> N >> M >> G >> S ;
    for (int i = 0 ; i < M ; ++i) {
        cin >> e[i].X.X >> e[i].X.Y >> e[i].Y.X >> e[i].Y.Y ; --e[i].X.X , --e[i].X.Y ;
    }
    sort (e,e+M,cmp) ;
    for (int i = 0 ; i < N ; ++i) {
        parent[i] = i ;
        siz[i] = 1 ;
    }
    ll BestAns = 1000LL * 1000 * 1000 * 1000 ;
    for (int i = 0 ; i < M ; ++i) {
//         cerr << e[i].X.X << " " << e[i].X.Y << "   : " << e[i].Y.X << " , " << e[i].Y.Y << endl ;
        Join (e[i].X.X , e[i].X.Y , e[i].Y.Y , i) ;
//         cerr << endl << "-------------------------------------------------------------------------------------------------------------------" << endl << endl << endl;
        BestAns = min (BestAns,e[i].Y.X*G+mSilver*S) ;
    }
    cout << BestAns << endl ;
    return 0 ;
}