题意:一堆人从1出发,到其他的点,然后从其他的点再回来,最短距离。和之前那个牛聚会题目一样,两次spfa。Silver Cow Party
由于这题的数据已经不能用邻接矩阵来储存,所以矩阵逆置就不能用了,所以需要用前向星进行反向建图,这里用到的也是一个很巧妙地方法。
我们需要在用结构体存边的信息的时候,多定一个边的起点信息,用来后面的反向建图。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<stack>
#include<algorithm>
#include<cmath>
#define N 1000010
#define inf 0x3f3f3f3f
using namespace std;
struct node
{
int u,v,w,next;
} s[N];
int n;
int vis[N];
int dis[N];
int head[N];
void add(int u,int v,int w,int tot)
{
s[tot].u = u;
s[tot].v = v;
s[tot].w = w;
s[tot].next = head[u];
head[u] = tot;
}
void spfa()
{
queue<int> q;
memset(vis,0,sizeof(vis));
for(int i = 1; i <= n; i++)
{
dis[i] = inf;
}
dis[1] = 0;
vis[1] = 1;
q.push(1);
while(q.size())
{
int u = q.front();
q.pop();
vis[u] = 0;
for(int i = head[u]; i != -1; i = s[i].next)
{
int v = s[i].v;
if(dis[v] > dis[u]+s[i].w)
{
dis[v] = dis[u]+s[i].w;
if(vis[v] == 0)
{
vis[v] = 1;
q.push(v);
}
}
}
}
}
int main()
{
int t,m,u,v,w;
scanf("%d",&t);
while(t--)
{
scanf("%d %d",&n,&m);
memset(head,-1,sizeof(head));
for(int i = 1; i <= m; i++)
{
scanf("%d %d %d",&u,&v,&w);
add(u,v,w,i);
}
spfa();
long long int sum = 0;
for(int i = 2; i <= n; i++)
{
sum += dis[i];
}
memset(head,-1,sizeof(head));
for(int i = 1; i <= m; i++)
{
add(s[i].v,s[i].u,s[i].w,i);
}
spfa();
for(int i = 2; i <= n; i++)
{
sum += dis[i];
}
printf("%lld\n",sum);
}
return 0;
}