// Slower C++ solution:
#include<cstdio>

#include<cstring>

#include<queue>

#include<vector>

using namespace std;

#define INF 1000000000

#define pb push_back

#define maxn 10001

struct Edge{

	int from, to, dist, cost;

};

struct HeapNode{

	int d, u, c;

	bool operator < (const HeapNode& a)const{

		if(d==a.d)	return c>a.c;

		return d>a.d;

	}

};

inline void IN(int& x){

	x=0;

	char c=getchar();

	while(c<48 || c>57)	c=getchar();

	while(c>=48 && c<=57){

		x=x*10+c-48;

		c=getchar();

	}

}

int n, m;

vector<Edge> edges;

vector<int> G[maxn];

vector<int> V[maxn];

bool done[maxn];

int d[maxn], p[maxn], c[maxn];

int ans;

void init(){

	for(int i=1; i<=n; i++){

		G[i].clear();

		V[i].clear();

	}

	edges.clear();

}

void add(int from, int to, int dist, int cost){

	edges.pb((Edge){from, to, dist, cost});

	m = edges.size();

	G[from].pb(m-1);

	V[from].pb(cost);

}

void dijkstra(int s){

	ans=0;

	priority_queue<HeapNode> Q;

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

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

	d[s]=0;

	c[s]=0;

	memset(done, 0, sizeof(done));

	Q.push((HeapNode){0,s,0});

	while(!Q.empty()){

		HeapNode x = Q.top(); Q.pop();

		int u=x.u;

		if(done[u])	continue;

		done[u]=1;

		ans += c[u];

		for(int i=0; i<G[u].size(); i++){

			Edge& e = edges[G[u][i]];

			if(d[e.to]>d[u]+e.dist || (d[e.to]==d[u]+e.dist && c[e.to]>V[u][i])){

				d[e.to] = d[u]+e.dist;

				p[e.to] = G[u][i];

				c[e.to] = V[u][i];

				Q.push((HeapNode){d[e.to],e.to,c[e.to]});

			}

		}

	}

	printf("%d\n", ans);

}

int k;

int main(){

	while(1){

		IN(n); IN(k);

		if(!n && (!k))	break;

		int a, b, c, d;

		init();

		while(k--){

			IN(a); IN(b); IN(c); IN(d);

			add(a, b, c, d);

			add(b, a, c, d);

		}

		dijkstra(1);

	}

	return 0;

}

// Faster C++ solution for the same problem (measured speedup: 1.2044854535016634x):
#include <cstdio>

#include <queue>

#include <vector>

#include <algorithm>



using namespace std;

const int INF = 0x3f3f3f3f;



const int maxn = 10240;



struct edge {

	int to, dis, cost;

	edge(int t, int d, int c) : to(t), dis(d), cost(c) {}

};





typedef pair<int, int> p;

priority_queue<p, vector<p>, greater<p> > q;

vector<edge> g[maxn];



int N, M;



void read_in() {

	//scanf("%d%d", &N, &M);

	for(int i = 1; i <= N; i++)

		g[i].clear();



	int from, to, dis, cost;

	for(int i = 1; i <= M; i++) {

		scanf("%d%d%d%d", &from, &to, &dis, &cost);

		g[from].push_back(edge(to, dis, cost));

		g[to].push_back(edge(from, dis, cost));

	}

}



int solve() {

	q.push(p(0, 1));



	const int INF = 0x7777777;

	int d[maxn];



	for(int i = 2; i <= N; i++) 

		d[i] = INF;

	d[1] = 0;



	while( !q.empty() ) {

		p t = q.top();

		q.pop();



		int to = t.second, dis = t.first;

        if(d[to] < dis) continue;

		for(unsigned int i = 0; i < g[to].size(); i++) {

			edge To = g[to][i];

			if(d[To.to] > d[to] + To.dis)

				d[To.to] = d[to] + To.dis,

				q.push(p(d[To.to], To.to));

		}

	}

	//show(d);

    int ans = 0;



    for(int i = 2; i <= N; i++) {

        int tmp = INF;



        for(int j = 0; j < g[i].size(); j++) {

            edge e = g[i][j];

            if(d[e.to] + e.dis == d[i] and e.cost < tmp)

                tmp = e.cost;

        }

        ans += tmp;

    }



    return ans;

}



int main() {

	while(scanf("%d %d", &N, &M) and N) {

		read_in();

		printf("%d\n", solve());

	}

	return 0;

}