/******************************************************
题目大意:
弱菜英语又是渣渣,题意是对着测试数据连猜带蒙出来的;
在一个有向图中,要求顶点1到其他的所有顶点往返的总共的最小花费;
另外给出的数据量略大,顶点数和边数都是1000000的范围;
算法分析:
这是一个最短路径问题;
由于数据范围很大,用邻接矩阵和dijkstra很可能超时超内存,所以采用邻接表建图;
在这个单向图中,求的是从第一个顶点到其他所有顶点的最短路径和其他所有顶点到第一个顶点的最短路径;
所以用两个邻接表分别寸正向图和反向图;
然后两次运用SPFA算法求以顶点1为起点的最短路径;
他们的和就是所求的最小花费;
*******************************************************/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<algorithm>
using namespace std;
const int N=1000005;
const int INF=1000000000;
typedef long long LL;
struct edge
{
int to;
int w;
edge *next;
};
edge *G1[N],*G2[N];//正向图,反向图
int inq[N];//每个顶点是否在队列中的标志
int n,m;
LL dist[N];
LL ans;
queue<int>Q;
void SPFA(int flag)
{
int v=1;//v为起点
for(int i=1; i<=n; i++)
{
dist[i]=INF;
inq[i]=0;
}
dist[v]=0;
inq[v]=1;
Q.push(v);
edge *temp;
while(!Q.empty())
{
int u=Q.front();
Q.pop();
inq[u]=0;
if(flag==1)
temp=G1[u];
else
temp=G2[u];
while(temp!=NULL)
{
int x=temp->to;
if(dist[x]>dist[u]+temp->w)//松弛
{
dist[x]=dist[u]+temp->w;
if(!inq[x])
{
Q.push(x);
inq[x]=1;
}
}
temp=temp->next;
}
}
for(int i=1; i<=n; i++)
{
// printf("dist[%d]==%d\n",i,dist[i]);
ans+=dist[i];
}
}
int main()
{
//freopen("C:\\Users\\Administrator\\Desktop\\kd.txt","r",stdin);
int t;
scanf("%d",&t);
while(t--)
{
memset(G1,0,sizeof(G1));
memset(G2,0,sizeof(G2));
scanf("%d%d",&n,&m);
int u,v,w;
edge *temp1,*temp2;
while(m--)
{
scanf("%d%d%d",&u,&v,&w);
temp1=new edge;//正向图
temp1->to=v;
temp1->w=w;
temp1->next=NULL;
if(G1[u]==NULL)
G1[u]=temp1;
else
{
temp1->next=G1[u];
G1[u]=temp1;
}
temp2=new edge;//反向图
temp2->to=u;
temp2->w=w;
temp2->next=NULL;
if(G2[v]==NULL)
G2[v]=temp2;
else
{
temp2->next=G2[v];
G2[v]=temp2;
}
}
ans=0;
SPFA(1);//正向
SPFA(0);//反向
printf("%lld\n",ans);
/*for(int i=1; i<=n; i++) //释放空间竟然释放的超时了。。
{
temp1=G1[i];
while(temp1!=NULL)
{
G1[i]=temp1->next;
delete temp1;
temp1=G1[i];
}
temp2=G2[i];
while(temp2!=NULL)
{
G2[i]=temp2->next;
delete temp2;
temp2=G2[i];
}
}*/
}
return 0;
/**************************************************************
Problem: 1511
User: Jarily
Language: C++
Result: Accepted
Time: 1938 MS
Memory: 43796K
****************************************************************/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<algorithm>
using namespace std;
const int N=1000005;
const int INF=1000000000;
typedef long long LL;
struct edge
{
int to;
int w;
int next;
};
edge G[2][N];//正向图,反向图
int head[2][N];
int inq[N];//每个顶点是否在队列中的标志
int n,m;
LL dist[N];
LL ans;
void Addedge(int u,int v,int w,int idx)
{
G[0][idx].w=w;
G[0][idx].to=v;
G[0][idx].next=head[0][u];
head[0][u]=idx;
G[1][idx].w=w;
G[1][idx].to=u;
G[1][idx].next=head[1][v];
head[1][v]=idx;
}
queue<int>Q;
void SPFA(int flag)
{
int v=1;//v为起点
for(int i=1; i<=n; i++)
{
dist[i]=INF;
inq[i]=0;
}
dist[v]=0;
inq[v]=1;
Q.push(v);
int temp;
while(!Q.empty())
{
int u=Q.front();
Q.pop();
inq[u]=0;
temp=head[flag][u];
int x,y;
while(temp!=-1)
{
x=G[flag][temp].to;
if(dist[x]>dist[u]+G[flag][temp].w)//松弛
{
dist[x]=dist[u]+G[flag][temp].w;
if(!inq[x])
{
Q.push(x);
inq[x]=1;
}
}
temp=G[flag][temp].next;
}
}
for(int i=1; i<=n; i++)
{
// printf("dist[%d]==%d\n",i,dist[i]);
ans+=dist[i];
}
}
int main()
{
// freopen("C:\\Users\\Administrator\\Desktop\\kd.txt","r",stdin);
int t;
scanf("%d",&t);
while(t--)
{
memset(G,0,sizeof(G));
memset(head,-1,sizeof(head));
scanf("%d%d",&n,&m);
int u,v,w;
for(int i=0; i<m; i++)
{
scanf("%d%d%d",&u,&v,&w);
Addedge(u,v,w,i);
}
ans=0;
SPFA(0);//正向
SPFA(1);//反向
printf("%lld\n",ans);
}
return 0;
}