题目链接:
题意:
给出一个M个点N条边的单向图 1 <= M,N <= 1000000. 给出每条边的两端和经过所需要的时间,求从第一点分别到达所有其他点(2~M)再回到第一点的最短时间
题解:
1 <= M,N <= 1000000. 邻接矩阵肯定会爆内存 所以spfa邻接表解决即可 注意好反向边的建立
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define maxx 0x3f3f3f3f
using namespace std;
struct node
{
int to,w;
int pre;
} edge[1000005][2];
int dis[1000005];
int vis[1000005];
int next[1000005][2];
int m,s1,s2,start,endd;
void addedge()
{
int u,v,weight;
scanf("%d%d%d",&u,&v,&weight);
edge[s1][0].to=v;
edge[s1][0].w=weight;
edge[s1][0].pre=next[u][0];
next[u][0]=s1++;
edge[s2][1].to=u;
edge[s2][1].w=weight;
edge[s2][1].pre=next[v][1];
next[v][1]=s2++;
return;
}
void spfa(int d)
{
for(int j=0; j<=m; j++)
{
vis[j]=0;
dis[j]=maxx;
}
queue<int>q;
int head;
dis[1]=0;
q.push(1);
while(!q.empty())
{
head=q.front();
q.pop();
vis[head]=0;
for(int i=next[head][d]; i!=-1; i=edge[i][d].pre)
{
if(dis[head]+edge[i][d].w<dis[edge[i][d].to])
{
dis[edge[i][d].to]=dis[head]+edge[i][d].w;
if(!vis[edge[i][d].to])
{
vis[edge[i][d].to]=1;
q.push(edge[i][d].to);
}
}
}
}
return;
}
int main()
{
int t,n,i,j;
__int64 ans;
scanf("%d",&t);
while(t--)
{
s1=s2=0;
ans=0;
scanf("%d%d",&m,&n);
for(i=0; i<=m; i++)
next[i][0]=next[i][1]=-1;
while(n--)
{
addedge();
}
spfa(0);
for(i=2; i<=m; i++)
ans=ans+dis[i];
spfa(1);
for(i=2; i<=m; i++)
ans=ans+dis[i];
printf("%I64d\n",ans);
}
return 0;
}