stablegradients/pie-gem5-pairs huggingface dataset:
// Slower C++ solution:
#include <bits/stdc++.h>

using namespace std;



typedef long long ll;

const int N = 10005;

const int M = 1000000007;



int n, m;

typedef int wtype;

struct Edge { int v; wtype d, c; };

vector<Edge> e[N];

wtype dist[N], cost[N];

int pre[N];

bool vis[N];

int SPFA(int src) {

  memset(dist, 0x3f, sizeof(dist)); dist[src] = 0;

  memset(cost, 0x3f, sizeof(cost)); cost[src] = 0;

  memset(vis, 0, sizeof(vis)); vis[src] = true;

  stack<int> que; que.push(src);

  while (!que.empty()) {

    int u = que.top(); que.pop();

    vis[u] = false;

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

      int v = e[u][i].v; wtype d = e[u][i].d, c = e[u][i].c;

      if (dist[v] > dist[u] + d || (dist[v] == dist[u] + d && cost[v] != 0x3f3f3f3f && cost[v] > c)) {

        dist[v] = dist[u] + d; cost[v] = c;

        if (!vis[v]) { vis[v] = true; que.push(v); }

      }

    }

  }

  int ret = 0;

  for (int i = 1; i <= n; i++) { ret += cost[i]; }

  return ret;

}



int main() {

  while (scanf("%d%d", &n, &m), n) {

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

    for (int i = 0, u, v, d, c; i < m; i++) {

      scanf("%d%d%d%d", &u, &v, &d, &c);

      e[u].push_back((Edge) {v, d, c});

      e[v].push_back((Edge) {u, d, c});

    }

    printf("%d\n", SPFA(1));

  }

}

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

#include<cstring>

#include<algorithm>

#include<vector>

#include<queue>



#define N 10010



struct Edge{

	int y;

	int z;

	int w;

	Edge(){}

	Edge(int y,int z,int w):y(y),z(z),w(w){}

	bool operator <(const Edge&_x)const{

		return this->z>_x.z || (this->z==_x.z && this->w>_x.w);

	}

};

#define Node Edge



std::vector<Edge> v[N];



void Dijkstra(int&);



int main(){

	while(true){

		int n,m;

		scanf("%d%d",&n,&m);

		if(!(n||m))

			break;

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

			v[i].clear();

		while(m--){

			int x,y,z,w;

			scanf("%d%d%d%d",&x,&y,&z,&w);

			v[x].push_back(Edge(y,z,w));

			v[y].push_back(Edge(x,z,w));

		}

		int ans=0;

		Dijkstra(ans);

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

	}

	return 0;

}



void Dijkstra(int &ans){

	std::priority_queue<Node> q;

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

	bool vis[N]={};

	while(q.size()){

		int x=q.top().y,z=q.top().z,w=q.top().w;

		q.pop();

		if(vis[x])

			continue;

		vis[x]=true;

		ans+=w;

		for(auto p:v[x])

			q.push(Node(p.y,z+p.z,p.w));

	}

}
// Slower C++ solution:
#include <iostream>

#include <algorithm>

#include <cstdio>

#include <queue>

#include <cstring>

#define INF 0x3f3f3f



using namespace std;

const int MAX_V=100001;

struct node

{

    int to, dis, cost, next;

}edge[MAX_V];



int head[MAX_V], d[MAX_V], mcost[MAX_V];//mcoat一个?点??一条?

bool vis[MAX_V];

int n, m, cnt;



void add_edge(int u, int v, int d, int c)

{

    edge[cnt].to=v;

    edge[cnt].dis=d;

    edge[cnt].cost=c;

    edge[cnt].next=head[u];

    head[u]=cnt++;

}



int spfa(int x)

{

    d[x]=0;         //必?！！！

    queue<int> que;

    que.push(x);

    vis[x]=true;

    while(!que.empty())

    {

        int u=que.front();

        que.pop();

        vis[u]=false;

        for(int i=head[u]; i!=-1; i=edge[i].next)

        {

            node e = edge[i];

            if(d[e.to] > d[u]+e.dis)

            {

                mcost[e.to]=e.cost;     ////??最小花?

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

                if(!vis[e.to])

                {

                    que.push(e.to);

                    vis[e.to]=true;

                }

            }

            else if(d[u]+e.dis==d[e.to] && e.cost<mcost[e.to])   ////??最小花?

                {

                    mcost[e.to]=e.cost;

                }

        }

    }

    int ans=0;

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

    {

     //   printf("\n%d\n", mcost[i]);

        ans+=mcost[i];

    }

    return ans;

}



int main()

{

    while(scanf("%d %d", &n, &m) && (m+n))

    {

        cnt=0;          //从0?始！！！

        memset(head, -1, sizeof(head)); //初始化在前面！！！！

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

        {

            int u, v, d, c;

            scanf("%d %d %d %d", &u, &v, &d, &c);

            add_edge(u,v,d,c);

            add_edge(v,u,d,c);      //双向的路！！！

        }



        //初始化

        memset(mcost, 0, sizeof(mcost));

        fill(d, d+n+1, INF);

        fill(vis, vis+n+1, false);



        int ans=spfa(1);

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

    }



    return 0;

}

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

#include<cstring>

#include<algorithm>

#include<vector>

#include<queue>



#define N 10010



struct Edge{

	int y;

	int z;

	int w;

	Edge(){}

	Edge(int y,int z,int w):y(y),z(z),w(w){}

	bool operator <(const Edge&_x)const{

		return this->z>_x.z || (this->z==_x.z && this->w>_x.w);

	}

};

#define Node Edge



std::vector<Edge> v[N];



void Dijkstra(int&);



int main(){

	while(true){

		int n,m;

		scanf("%d%d",&n,&m);

		if(!(n||m))

			break;

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

			v[i].clear();

		while(m--){

			int x,y,z,w;

			scanf("%d%d%d%d",&x,&y,&z,&w);

			v[x].push_back(Edge(y,z,w));

			v[y].push_back(Edge(x,z,w));

		}

		int ans=0;

		Dijkstra(ans);

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

	}

	return 0;

}



void Dijkstra(int &ans){

	std::priority_queue<Node> q;

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

	bool vis[N]={};

	while(q.size()){

		int x=q.top().y,z=q.top().z,w=q.top().w;

		q.pop();

		if(vis[x])

			continue;

		vis[x]=true;

		ans+=w;

		for(auto p:v[x])

			q.push(Node(p.y,z+p.z,p.w));

	}

}
// Slower C++ solution:
#include <iostream>

#include <cstring>

#include <queue>

#define inf 0x3f3f3f3f

#define maxm 10005

#define maxn 40005



using namespace std;



int m,n;

long long edgenum,head[maxm],dis[maxm],num[maxm],ans;

bool vis[maxm];



struct node

{

    int from,to,len,cost,next;

}edge[maxn];



void init()

{

    memset(head,-1,sizeof(head));

    memset(vis,0,sizeof(vis));

    memset(dis,inf,sizeof(dis));

    memset(num,inf,sizeof(num));

    edgenum=0;

}



void add(int u,int v,int len,int cost)

{

    node tp={u,v,len,cost,head[u]};

    edge[edgenum]=tp;

    head[u]=edgenum++;

}



long long SPFA(int st)

{

     queue<int> q;

     q.push(st);

     vis[st]=1;

     dis[st]=0;

     num[st]=0;

     ans=0;

     while(!q.empty())

     {

          int tmp=q.front();

          q.pop();

          vis[tmp]=0;

          for(int i=head[tmp];i!=-1;i=edge[i].next)

          {

                if((dis[edge[i].to]>dis[tmp]+edge[i].len)||((dis[edge[i].to]==dis[tmp]+edge[i].len)&&(num[edge[i].to]>edge[i].cost)))

                {

                    dis[edge[i].to]=dis[tmp]+edge[i].len;

                    num[edge[i].to]=edge[i].cost;

                    if(!vis[edge[i].to])

                    {

                        q.push(edge[i].to);

                        vis[edge[i].to]=1;

                    }

                }

          }

     }

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

        ans+=num[i];

     return ans;

}



int main()

{

    int u,v,len,cost;

    while(cin>>m>>n&&m)

    {

        init();

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

        {

            cin>>u>>v>>len>>cost;

            add(u,v,len,cost);

            add(v,u,len,cost);

        }

        cout<<SPFA(1)<<endl;

    }

    return 0;

}

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

#include<cstring>

#include<algorithm>

#include<vector>

#include<queue>



#define N 10010



struct Edge{

	int y;

	int z;

	int w;

	Edge(){}

	Edge(int y,int z,int w):y(y),z(z),w(w){}

	bool operator <(const Edge&_x)const{

		return this->z>_x.z || (this->z==_x.z && this->w>_x.w);

	}

};

#define Node Edge



std::vector<Edge> v[N];



void Dijkstra(int&);



int main(){

	while(true){

		int n,m;

		scanf("%d%d",&n,&m);

		if(!(n||m))

			break;

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

			v[i].clear();

		while(m--){

			int x,y,z,w;

			scanf("%d%d%d%d",&x,&y,&z,&w);

			v[x].push_back(Edge(y,z,w));

			v[y].push_back(Edge(x,z,w));

		}

		int ans=0;

		Dijkstra(ans);

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

	}

	return 0;

}



void Dijkstra(int &ans){

	std::priority_queue<Node> q;

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

	bool vis[N]={};

	while(q.size()){

		int x=q.top().y,z=q.top().z,w=q.top().w;

		q.pop();

		if(vis[x])

			continue;

		vis[x]=true;

		ans+=w;

		for(auto p:v[x])

			q.push(Node(p.y,z+p.z,p.w));

	}

}
// Slower C++ solution:
#include <iostream>

#include <queue>

#include <functional>

#include <cstring>

using namespace std;



struct edge{

    int v, d, c;

    edge(){}

    edge(int v, int d, int c) : v(v),d(d),c(c){}

};



int N, M;

const int INF = 0x3f3f3f3f;

typedef pair<int, int> P;//距?， ?点

int d[10665];



vector<edge> G[10665];



void dijkstra(int s){

    priority_queue<P, vector<P>,greater<P> > que;

    memset(d, INF, sizeof(d));

    d[s] = 0;

    que.push(P(0,s));

    while(!que.empty())

    {

        P p = que.top();

        que.pop();

        int q = p.second;

        if(d[q] < p.first) continue;

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

        {

            edge e = G[q][i];

            if(d[e.v] > d[q] + e.d)

            {

                d[e.v] = d[q] + e.d;

                que.push(P(d[e.v], e.v));

            }

        }

    }

}





int main()

{

    while(cin >> N >> M)

    {

        if(!N) break;

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

		{

			G[i].clear();

		}

        for(int i = 0; i < M; i++)

        {

            int u,t,c,d;

            cin >> u >> t >> d >> c;

            u--;t--;

            G[u].push_back(edge(t,d,c));

            G[t].push_back(edge(u,d,c));

        }

        dijkstra(0);

        int ans=0;

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

        {

            int mincost = INF;

            for(int j = 0; j < G[k].size(); j++)

            {

                if(d[G[k][j].v]+G[k][j].d == d[k]

                 && G[k][j].c < mincost)

                    mincost = G[k][j].c;

            }

            ans += mincost;

        }

        cout << ans << endl;

    }

    return 0;

}

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

#include<cstring>

#include<algorithm>

#include<vector>

#include<queue>



#define N 10010



struct Edge{

	int y;

	int z;

	int w;

	Edge(){}

	Edge(int y,int z,int w):y(y),z(z),w(w){}

	bool operator <(const Edge&_x)const{

		return this->z>_x.z || (this->z==_x.z && this->w>_x.w);

	}

};

#define Node Edge



std::vector<Edge> v[N];



void Dijkstra(int&);



int main(){

	while(true){

		int n,m;

		scanf("%d%d",&n,&m);

		if(!(n||m))

			break;

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

			v[i].clear();

		while(m--){

			int x,y,z,w;

			scanf("%d%d%d%d",&x,&y,&z,&w);

			v[x].push_back(Edge(y,z,w));

			v[y].push_back(Edge(x,z,w));

		}

		int ans=0;

		Dijkstra(ans);

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

	}

	return 0;

}



void Dijkstra(int &ans){

	std::priority_queue<Node> q;

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

	bool vis[N]={};

	while(q.size()){

		int x=q.top().y,z=q.top().z,w=q.top().w;

		q.pop();

		if(vis[x])

			continue;

		vis[x]=true;

		ans+=w;

		for(auto p:v[x])

			q.push(Node(p.y,z+p.z,p.w));

	}

}
// Slower C++ solution:
#include<iostream>

#include<vector>

#include<queue>

#include<algorithm>

#include<cstring>

using namespace std;

const int maxn  = 1e4+10;

const int INF = 0x3f3f3f3f;

typedef pair<int,int> P;

struct edge{

	int to,dis,cost;

		

};



int d[maxn];

int value[maxn];



int N,M;



int dijkstra(vector<edge>G[])

{



	memset(d,INF,sizeof(d));

	//memset(value,INF,sizeof(value));

	priority_queue<P,vector<P>,greater<P> > que;

		

	d[1] = 0;

	value[1] = 0;

	que.push(P(d[1],1));

	

	int res = 0;

	while(!que.empty())

	{

		P p  = que.top(); que.pop();

		

		int v = p.second;

		if(d[v] < p.first)

			continue;

			

		res += value[v];

		

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

		{

			edge e = G[v][i];

			if(d[e.to] == d[v] + e.dis)

				value[e.to] = min(value[e.to],e.cost);

			if(d[e.to] > d[v] + e.dis)

			{

				d[e.to] = d[v] + e.dis;

				que.push(P(d[e.to],e.to));

				

				value[e.to] = e.cost;

			}

		}

	}

	return res;

	

}



int main()

{



	//freopen("c:\\users\\administrator\\desktop\\in.txt","r",stdin);

	while(cin >> N >> M, N||M)

	{

		

		vector<edge> G[maxn];

		for(int i =0; i < M; i++)

		{

			int u,v,d,c;

			edge e;

			cin >> u >> v >> d >> c;

			e.to= v, e.dis= d, e.cost =c;

			G[u].push_back(e);

			e.to= u;

			G[v].push_back(e);	

		}

		

		int res = dijkstra(G);

		cout << res <<endl;

	}		

} 

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

#include<cstring>

#include<algorithm>

#include<vector>

#include<queue>



#define N 10010



struct Edge{

	int y;

	int z;

	int w;

	Edge(){}

	Edge(int y,int z,int w):y(y),z(z),w(w){}

	bool operator <(const Edge&_x)const{

		return this->z>_x.z || (this->z==_x.z && this->w>_x.w);

	}

};

#define Node Edge



std::vector<Edge> v[N];



void Dijkstra(int&);



int main(){

	while(true){

		int n,m;

		scanf("%d%d",&n,&m);

		if(!(n||m))

			break;

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

			v[i].clear();

		while(m--){

			int x,y,z,w;

			scanf("%d%d%d%d",&x,&y,&z,&w);

			v[x].push_back(Edge(y,z,w));

			v[y].push_back(Edge(x,z,w));

		}

		int ans=0;

		Dijkstra(ans);

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

	}

	return 0;

}



void Dijkstra(int &ans){

	std::priority_queue<Node> q;

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

	bool vis[N]={};

	while(q.size()){

		int x=q.top().y,z=q.top().z,w=q.top().w;

		q.pop();

		if(vis[x])

			continue;

		vis[x]=true;

		ans+=w;

		for(auto p:v[x])

			q.push(Node(p.y,z+p.z,p.w));

	}

}
// Slower C++ solution:
#include <bits/stdc++.h>

using namespace std;

struct node{

    int next,d,c;

};

const int maxn=10005;

int n,m;

int d[maxn],c[maxn];

bool vis[maxn];

void init()

{

    for(int i=0;i<maxn;i++)

        d[i]=c[i]=1e9,vis[i]=0;

}

int main()

{

    while(~scanf("%d%d",&n,&m))

    {

        if(n==0&&m==0) return 0;

        init();vector<node> v[maxn];

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

        {

            int x,y,d,c;

            scanf("%d%d%d%d",&x,&y,&d,&c);

            v[x].push_back(node{y,d,c});

            v[y].push_back(node{x,d,c});

        }

        queue<int> q;

        q.push(1);

        d[1]=c[1]=0;vis[1]=1;

        while(!q.empty())

        {

            int u=q.front();q.pop();vis[u]=0;

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

            {

                int nx=v[u][i].next;

                if(d[nx]==d[u]+v[u][i].d&&c[nx]>v[u][i].c){

                        c[nx]=v[u][i].c;

                }

                if(d[nx]>d[u]+v[u][i].d)

                {

                    d[nx]=d[u]+v[u][i].d;

                    c[nx]=v[u][i].c;

                    if(vis[nx]) continue;

                    vis[nx]=1;

                    q.push(nx);

                }

            }

        }

        int ans=0;

        for(int i=2;i<=n;i++) ans+=c[i];

        cout<<ans<<endl;

    }

    return 0;

}

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

#include<cstring>

#include<algorithm>

#include<vector>

#include<queue>



#define N 10010



struct Edge{

	int y;

	int z;

	int w;

	Edge(){}

	Edge(int y,int z,int w):y(y),z(z),w(w){}

	bool operator <(const Edge&_x)const{

		return this->z>_x.z || (this->z==_x.z && this->w>_x.w);

	}

};

#define Node Edge



std::vector<Edge> v[N];



void Dijkstra(int&);



int main(){

	while(true){

		int n,m;

		scanf("%d%d",&n,&m);

		if(!(n||m))

			break;

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

			v[i].clear();

		while(m--){

			int x,y,z,w;

			scanf("%d%d%d%d",&x,&y,&z,&w);

			v[x].push_back(Edge(y,z,w));

			v[y].push_back(Edge(x,z,w));

		}

		int ans=0;

		Dijkstra(ans);

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

	}

	return 0;

}



void Dijkstra(int &ans){

	std::priority_queue<Node> q;

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

	bool vis[N]={};

	while(q.size()){

		int x=q.top().y,z=q.top().z,w=q.top().w;

		q.pop();

		if(vis[x])

			continue;

		vis[x]=true;

		ans+=w;

		for(auto p:v[x])

			q.push(Node(p.y,z+p.z,p.w));

	}

}
// Slower C++ solution:
#include<iostream>

#include<cstdio>

#include<cstdlib>

#include<string>

#include<cstring>

#include<algorithm>

#include<queue>

#include<vector>

#define N 20100

#define M 50010

#define rg register

using namespace std;

typedef long long ll;

typedef double db;

int n,m,tot=0;

int dis[N],head[N],vis[N];

int nxt[M],to[M],w[M],c[M];

void link(int x,int y,int z,int v){

	nxt[tot]=head[x],to[tot]=y,w[tot]=z,c[tot]=v,head[x]=tot++;

}

void spfa(){

	queue <int> q;

	memset(dis,0x3f,sizeof(dis));

	memset(vis,0,sizeof(vis));

	q.push(1),dis[1]=0,vis[1]=1;

	while (!q.empty()){

		int x=q.front();q.pop();

		for (int i=head[x];i!=-1;i=nxt[i]){

			int v=to[i];

			if (dis[v]<=dis[x]+w[i]) continue;

			dis[v]=dis[x]+w[i];

			if (!vis[v]) vis[v]=1,q.push(v);

		}

		vis[x]=0;

	}

}

int main(){

//	freopen ("2249.in","r",stdin);

//	freopen ("2249.out","w",stdout);

	while (scanf ("%d%d",&n,&m)&&(n||m)){

		memset(head,-1,sizeof(head));

		tot=0;int x,y,z,v;

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

			scanf ("%d%d%d%d",&x,&y,&z,&v);

			link(x,y,z,v),link(y,x,z,v);

		}

		spfa();

		int ans=0;

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

			int mx=2000;

			for (int j=head[i];j!=-1;j=nxt[j]){

				v=to[j];

				if (dis[i]==dis[v]+w[j]) mx=min(mx,c[j]);

			}

			ans+=mx;

		}

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

	

	}

	return 0;

}

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

#include<cstring>

#include<algorithm>

#include<vector>

#include<queue>



#define N 10010



struct Edge{

	int y;

	int z;

	int w;

	Edge(){}

	Edge(int y,int z,int w):y(y),z(z),w(w){}

	bool operator <(const Edge&_x)const{

		return this->z>_x.z || (this->z==_x.z && this->w>_x.w);

	}

};

#define Node Edge



std::vector<Edge> v[N];



void Dijkstra(int&);



int main(){

	while(true){

		int n,m;

		scanf("%d%d",&n,&m);

		if(!(n||m))

			break;

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

			v[i].clear();

		while(m--){

			int x,y,z,w;

			scanf("%d%d%d%d",&x,&y,&z,&w);

			v[x].push_back(Edge(y,z,w));

			v[y].push_back(Edge(x,z,w));

		}

		int ans=0;

		Dijkstra(ans);

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

	}

	return 0;

}



void Dijkstra(int &ans){

	std::priority_queue<Node> q;

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

	bool vis[N]={};

	while(q.size()){

		int x=q.top().y,z=q.top().z,w=q.top().w;

		q.pop();

		if(vis[x])

			continue;

		vis[x]=true;

		ans+=w;

		for(auto p:v[x])

			q.push(Node(p.y,z+p.z,p.w));

	}

}
// Slower C++ solution:
#include<queue>

#include<cstdio>

#include<vector>

#include<cstring>

#include<iostream>

#include<algorithm>

#define RG register

#define LL long long

#define fre(a) freopen(a".in","r",stdin);//freopen(a".out","w",stdout);

using namespace std;

const int MAXN=50000;

int n,m,num;

int head[MAXN],to[MAXN],len[MAXN],cost[MAXN],Next[MAXN];

int dis[MAXN],pre[MAXN],pree[MAXN];

bool vis[MAXN],use[MAXN];

queue<int>que;

void add(int f,int t,int l,int c)

{

   Next[++num]=head[f];

   to[num]=t;

   len[num]=l;

   cost[num]=c;

   head[f]=num;

}

void SPFA()

{

   que.push(1);

   dis[1]=0;

   while(!que.empty())

      {

	 int now=que.front();

	 que.pop(); vis[now]=0;

	 for(int i=head[now];i;i=Next[i])

	    {

	       int son=to[i];

	       if(dis[now]+len[i]<dis[son])

		  {

		     dis[son]=dis[now]+len[i];

		     pre[son]=now;

		     pree[son]=i;

		     if(!vis[son])

			{

			   vis[son]=1;

			   que.push(son);

			}

		  }

	       else if(dis[now]+len[i]==dis[son])

		  {

		     if(cost[i]<cost[pree[son]])

			pree[son]=i,pre[son]=now;

		  }

	    }

      }

}

int main()

{

   //fre("1");

   while(1)

      {

	 scanf("%d%d",&n,&m);

	 if(n==0&&m==0)return 0;

	 num=0;

	 memset(head,0,sizeof head);

	 for(int i=1,a,b,c,d;i<=m;i++)

	    {

	       scanf("%d%d%d%d",&a,&b,&c,&d);

	       add(a,b,c,d); add(b,a,c,d);

	    }

	 memset(dis,0x3f3f3f3f,sizeof dis);

	 memset(vis,0,sizeof vis);

	 memset(use,0,sizeof use);

	 //memset(pree,0,sizeof pree);

	 SPFA();

	 //for(int i=1;i<=n;i++)printf("dis[%d]=%d\n",i,dis[i]);printf("----------------\n");

	 int ans=0;

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

	    for(int j=i;j>1;j=pre[j])

	       if(!use[pree[j]])

		  ans+=cost[pree[j]],use[pree[j]]=1;

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

      }

   return 0;

}

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

#include<cstring>

#include<algorithm>

#include<vector>

#include<queue>



#define N 10010



struct Edge{

	int y;

	int z;

	int w;

	Edge(){}

	Edge(int y,int z,int w):y(y),z(z),w(w){}

	bool operator <(const Edge&_x)const{

		return this->z>_x.z || (this->z==_x.z && this->w>_x.w);

	}

};

#define Node Edge



std::vector<Edge> v[N];



void Dijkstra(int&);



int main(){

	while(true){

		int n,m;

		scanf("%d%d",&n,&m);

		if(!(n||m))

			break;

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

			v[i].clear();

		while(m--){

			int x,y,z,w;

			scanf("%d%d%d%d",&x,&y,&z,&w);

			v[x].push_back(Edge(y,z,w));

			v[y].push_back(Edge(x,z,w));

		}

		int ans=0;

		Dijkstra(ans);

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

	}

	return 0;

}



void Dijkstra(int &ans){

	std::priority_queue<Node> q;

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

	bool vis[N]={};

	while(q.size()){

		int x=q.top().y,z=q.top().z,w=q.top().w;

		q.pop();

		if(vis[x])

			continue;

		vis[x]=true;

		ans+=w;

		for(auto p:v[x])

			q.push(Node(p.y,z+p.z,p.w));

	}

}
// Slower C++ solution:
#include "cstring"

#include "cstdio"

#include "vector"

#include "queue"

using namespace std;



const int maxn=11000;



struct edge{int to,d,c;};

edge edges[4100000];

int p;



vector<int>g[maxn];



int dis[maxn],vis[maxn],cos[maxn];

int n,m,sn;



void add(int u,int v,int d,int c)

{

	edges[++p].d=d;

	edges[p].to=v;

	edges[p].c=c;

	g[u].push_back(p);

}



int spfa(int s)

{

	memset(cos,0x3f3f3f3f,sizeof(cos));

	memset(dis,0x3f3f3f3f,sizeof(dis));

	memset(vis,0,sizeof(vis));

	

	queue<int>qn;

	qn.push(s);

	dis[s]=0;

	cos[s]=0;

	vis[s]=1;

	

	while(!qn.empty())

	{

		int nn=qn.front();qn.pop();

		vis[nn]=0;

		for(int i=0,d=g[nn].size();i<d;i++)

		{

			edge &e= edges[g[nn][i]];

			if(dis[e.to]>dis[nn]+e.d || ((dis[e.to]==dis[nn]+e.d) && cos[e.to]>e.c))

			{

				dis[e.to]=dis[nn]+e.d;

				cos[e.to]=e.c;

				

				if(!vis[e.to])

				{

					qn.push(e.to);

					vis[e.to]=1;

				}

			}

		}	

	}

	return 0;

}



int main()

{

	//freopen("q.txt","r",stdin);

	int u,v,d,c;

	while(~scanf("%d%d",&n,&m))

	{

		if(n==0 && m==0)break;

		for(int i=0;i<=n;i++)

			g[i].clear();

		p=0;

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

		{

			scanf("%d%d%d%d",&u,&v,&d,&c);

			add(u,v,d,c);

			add(v,u,d,c);

		}

		int ans=0;

		spfa(1);

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

			ans+=cos[i];

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

	}

	return 0;

} 


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

#include<cstring>

#include<algorithm>

#include<vector>

#include<queue>



#define N 10010



struct Edge{

	int y;

	int z;

	int w;

	Edge(){}

	Edge(int y,int z,int w):y(y),z(z),w(w){}

	bool operator <(const Edge&_x)const{

		return this->z>_x.z || (this->z==_x.z && this->w>_x.w);

	}

};

#define Node Edge



std::vector<Edge> v[N];



void Dijkstra(int&);



int main(){

	while(true){

		int n,m;

		scanf("%d%d",&n,&m);

		if(!(n||m))

			break;

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

			v[i].clear();

		while(m--){

			int x,y,z,w;

			scanf("%d%d%d%d",&x,&y,&z,&w);

			v[x].push_back(Edge(y,z,w));

			v[y].push_back(Edge(x,z,w));

		}

		int ans=0;

		Dijkstra(ans);

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

	}

	return 0;

}



void Dijkstra(int &ans){

	std::priority_queue<Node> q;

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

	bool vis[N]={};

	while(q.size()){

		int x=q.top().y,z=q.top().z,w=q.top().w;

		q.pop();

		if(vis[x])

			continue;

		vis[x]=true;

		ans+=w;

		for(auto p:v[x])

			q.push(Node(p.y,z+p.z,p.w));

	}

}