题意:从1号车站到所有车站,再从所有车站到1号,花费总和最少为多少?注意公交车是单向的。
题解:从1到所有车站就一次dijkstra,然后回来怎么做呢?就是把所有的路反向,再走一次dijkstra。这样子原先你可以从1到其它结点的路不可以走了,但是从其它结点到1的路就通了。
内存有点紧G++内存超了,但C++AC
标准的FIFO的Dijkstra代码(MLE)
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <functional>
#include <cstdio>
#include <iostream>
using namespace std;
int const N = 1000000 + 10;
typedef long long ll;
typedef pair<ll,int>pli;
ll const inf = 0x7f7f7f7f;
int n,m;
ll dis[N];
struct Edge
{
int from,to;
ll dist;
Edge(){};
Edge(int ff,int tt,ll dd):from(ff),to(tt),dist(dd){};
};
vector<Edge>G1[N],G2[N];
priority_queue<pli,vector<pli>,greater<pli> >q;
ll Dijkstra(vector<Edge>G[N]){
for(int i=1;i<=n;i++) dis[i] = inf;
dis[1] = 0;
q.push(make_pair(0,1));
while(!q.empty()){
pli p = q.top(); q.pop();
int u = p.second;
if(dis[u] < p.first) continue;
for(int i=0;i<G[u].size();i++){
Edge e = G[u][i];
if(dis[e.to] > dis[e.from] + e.dist){
dis[e.to] = dis[e.from] + e.dist;
q.push(make_pair(dis[e.to],e.to));
}
}
}
ll sum = 0;
for(int i=1;i<=n;i++) sum += dis[i];
return sum;
}
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m); //n表示车站的数量,m表示线路的数量
for(int i=1;i<=n;i++) G1[i].clear(),G2[i].clear();
for(int i=1;i<=m;i++){
int from,to;
ll dist;
scanf("%d%d%lld",&from,&to,&dist);
G1[from].push_back(Edge(from,to,dist));
G2[to].push_back(Edge(to,from,dist));
}
ll sum = Dijkstra(G1);
sum += Dijkstra(G2);
cout<<sum<<endl;
}
return 0;
}
优化了一下,把pair去掉了,边结构体去掉了头结点
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <functional>
#include <cstdio>
#include <iostream>
#define inf 0x3f3f3f3f
using namespace std;
const int N = 1000000 + 10;
int n,m,dis[N],vis[N];
struct Node{
int u,len;
Node(){};
Node(int uu=0,int ll=0):u(uu),len(ll){};
bool operator < (const Node &a)const{
return len > a.len;
}
};
vector<Node>G1[N],G2[N];
int Dijkstra(vector<Node>G[]){
memset(vis,0,sizeof(vis));
for(int i=0;i<=n;i++) dis[i] = inf;
dis[1] = 0;
priority_queue<Node>q;
q.push(Node(1,0));
while(!q.empty()){
Node p = q.top(); q.pop();
int v = p.u;
if(vis[v]) continue;
vis[v] = 1;
for(int i=0;i<G[v].size();i++){
Node e = G[v][i];
if(vis[e.u]) continue;
if(dis[e.u] > dis[v] + e.len){
dis[e.u] = dis[v] + e.len;
q.push(Node(e.u,dis[e.u]));
}
}
}
int sum = 0;
for(int i=1;i<=n;i++) sum += dis[i];
return sum;
}
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m); //n表示车站的数量,m表示线路的数量
for(int i=0;i<=n;i++) G1[i].clear(),G2[i].clear();
for(int i=0;i<m;i++){
int from,to,dist;
scanf("%d%d%d",&from,&to,&dist);
G1[from].push_back(Node(to,dist));
G2[to].push_back(Node(from,dist));
}
int sum = Dijkstra(G1);
sum += Dijkstra(G2);
cout<<sum<<endl;
}
return 0;
}