题意: 有N个点 求从1出发到各个点的最小花费和从各个点回到1的花费的和
正反两次spfa
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
#include<string.h>
using namespace std;
typedef long long ll;
const int maxn=1e6+6;
const int inf=0x3f3f3f3f;
int head[maxn],vis[maxn];
ll dis[maxn];
int a,b,n,m,e;
ll c;
struct node{
int u;
int v;
ll w;
int next;
}mp[maxn];
void build(int u,int v,ll w)
{
mp[e].u=u;
mp[e].v=v;
mp[e].w=w;
mp[e].next=head[u];
head[u]=e;
e++;
}
void begin()
{
memset(head,-1,sizeof(head));
for(int i=1;i<maxn;i++)
{
mp[i].next=-1;
}
e=0;
int a,b;
ll c;
for(int i=0;i<m;i++)
{
scanf("%d%d%lld",&a,&b,&c);
build(a,b,c);
}
}
void end()
{
memset(head,-1,sizeof(head));
for(int i=1;i<maxn;i++)
{
mp[i].next=-1;
}
e=0;
for(int i=0;i<m;i++)
{
build(mp[i].v,mp[i].u,mp[i].w);
}
}
int spfa(int x)
{
int u,v,w;
memset(vis,0,sizeof(vis));
memset(dis,inf,sizeof(dis));
dis[x]=0;
queue<int> q;
while(!q.empty())
q.pop();
q.push(x);
vis[x]=1;
while(!q.empty())
{
u=q.front();
q.pop();
vis[u]=0;
for(int i=head[u];i!=-1;i=mp[i].next)
{
v=mp[i].v;
w=mp[i].w;
if(dis[v]>dis[u]+w)
{
dis[v]=dis[u]+w;
if(!vis[v])
{
q.push(v);
vis[v]=1;
}
}
}
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
ll sum1=0,sum2=0,sum;
scanf("%d%d",&n,&m);
begin();
spfa(1);
for(int i=1;i<=n;i++)
{
sum1+=dis[i];
}
end();
spfa(1);
for(int i=1;i<=n;i++)
{
sum2+=dis[i];
}
cout<<sum1+sum2<<endl;
}
return 0;
}