题意:求从出发点到每个车站的最短距离+从每个车站回到出发点的最短距离是多少
思路:如果从每个点到出发点求一次最短路10^5个点10^5次求SPFA也会超时,那么如果我们反向建边的话可以只用一次SPFA,因为是单向边嘛,把箭头反过来,再求一次起点到各点的最短距离不就行了?
#include<cstdio> #include<cstring> #include<queue> using namespace std; const int inf = 0x3f3f3f3f; const int M = 1e6+10; struct Edge { int u,v,w; } e[M]; int v[M],w[M],next[M],head[M],d[M],edge;//head初始化为-1,模拟邻接表 void init(int V) { // fill(v,v+V,0); // fill(w,w+V,inf); //fill(next,next+V,-1); fill(d,d+V,inf); fill(head,head+V,-1); edge = 0; } void addedge(int a,int b,int x)//主要如果是无向图的话,每条边要执行两次这个,a,b反过来就行 { v[edge]=b; w[edge]=x; next[edge]=head[a]; head[a]=edge++; } void SPFA(int s) { queue<int> q; d[s]=0; q.push(s); while(!q.empty()) { int u = q.front(); q.pop(); for(int i=head[u]; i!=-1; i=next[i]) { if(d[v[i]]>d[u]+w[i]) { d[v[i]]=d[u]+w[i]; q.push(v[i]); } } } } int main() { #ifdef xxz freopen("in.txt","r",stdin); #endif // xxz int n,sum,p,q; scanf("%d",&n); while(n--) { sum = 0; scanf("%d%d",&p,&q); init(p+1); for(int i = 0; i < q; i++) { scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w); addedge(e[i].u,e[i].v,e[i].w); } SPFA(1); for(int i = 2; i <= p; i++) { sum += d[i]; } init(p+1); for(int i = 0; i < q; i++) { addedge(e[i].v,e[i].u,e[i].w); } SPFA(1); for(int i = 2; i <= p; i++) { sum += d[i]; } printf("%d\n",sum); } return 0; }
时间: 2024-10-12 04:10:02