题目大意:给出n个点和n条有向边,求所有点到源点1的来回最短路之和(保证每个点都可以往返源点1)
解题思路:这个数据范围太大,明显的不能用floyd,dijstra,bellman-ford这些算法,用spfa的话也不能用邻接矩阵存,因为点太多了,所以采用spfa的邻接表存储搞定稍微有点注意的地方是,来回之和只需要将所有的边反向再从1到所有点求最短路就是他们的最短回路
注意数据较大 使用long long
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
typedef long long ll;
const int maxn=1000005;
const ll inf=1LL<<60;
struct edge
{
int v,k,next;
void init(int tv,int tk,int tnext)
{
v=tv,k=tk,next=tnext;
}
}e[2][maxn];
int link[2][maxn];
ll d[maxn],ans;
bool inque[maxn];
int ne,n;
void spfa(int c)
{
memset(inque,0,sizeof(inque));
int u,v,p;
for(p=1;p<=n;p++)
{
d[p]=inf;
}
queue<int> q;
q.push(1);
inque[1]=true;
d[1]=0;
while(!q.empty())
{
u=q.front();
q.pop();
inque[u]=false;
for(p=link[c][u];p!=-1;p=e[c][p].next)
{
v=e[c][p].v;
if(d[v]>d[u]+e[c][p].k)
{
d[v]=d[u]+e[c][p].k;
if(!inque[v])
{
q.push(v);
inque[v]=true;
}
}
}
}
}
int main()
{
int T,m;
scanf("%d",&T);
while(T--)
{
ne=0;
memset(link,-1,sizeof(link));
int i,u,v,k;
scanf("%d%d",&n,&m);
for(i=0;i<m;i++)
{
scanf("%d%d%d",&u,&v,&k);
e[0][ne].init(v,k,link[0][u]);
link[0][u]=ne;
e[1][ne].init(u,k,link[1][v]);
link[1][v]=ne++;
}
ans=0;
spfa(0);
for(i=1;i<=n;i++)
{
ans+=d[i];
}
spfa(1);
for(i=1;i<=n;i++)
{
ans+=d[i];
}
printf("%lld\n",ans);
}
return 0;
}