题意:
本题大意:有n个公交站站点,有那个志愿者,要求每个志愿者到一个公交站点接待路人,站台号为1,2,3到n,所有的志愿者从1号站台出发,最后还要全部返回1号站台,但是这里的公交车比较奇怪,总是在两个站台之间来往,而且只往一个方向载客,不同的路线费用不同
思路:
两次最短路。第一次从s到各个点,第二次把图反转过来,再跑一次。加和输出。
这个图太大,矩阵存不下不好反转,所以直接准备两个图的空间。
注意用long long!!!
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
typedef long long LL;
const int INF = 1000010000;
const int maxn = 1000000+5;
using namespace std;
int n,m;
int head[2][maxn], cur[2];
struct Edge{
LL v, w, next;
};
Edge edges[2][maxn];
void init(int a){
for(int i = 0; i <= a; ++i) head[0][i] = head[1][i] = -1;
cur[0] = cur[1] = 0;
}
void addEdge(int u, int v, int w){
edges[0][cur[0]].v = v; edges[0][cur[0]].w = w;
edges[0][cur[0]].next = head[0][u]; head[0][u] = cur[0]++;
edges[1][cur[1]].v = u; edges[1][cur[1]].w = w;
edges[1][cur[1]].next = head[1][v]; head[1][v] = cur[1]++;
}
bool vis[maxn];
LL d[maxn];
struct Node{
LL u,d;
Node(int a, int b):u(a),d(b){}
bool operator < (const Node& rhs) const{
return d > rhs.d;
}
};
void Dijkstra(int s, int b){
for(int i = 1; i <= n; ++i) { d[i] = INF; vis[i] = 0; }
d[s] = 0;
priority_queue<Node> Q;
Q.push(Node(s, 0));
while(!Q.empty()){
Node t = Q.top(); Q.pop();
int u = t.u;
if(vis[u]) continue;
vis[u] = 1;
for(int i = head[b][u]; i != -1; i = edges[b][i].next){
LL v = edges[b][i].v, w = edges[b][i].w;
if(d[v] > d[u] + w){
d[v] = d[u] + w;
Q.push(Node(v, d[v]));
}
}
}
}
int main()
{
//freopen("in.txt","r",stdin);
int s = 1;
int T; scanf("%d",&T);
while(T--){
//memset(G, 0, sizeof(G));
scanf("%d%d",&n,&m);
init(n);
for(int i = 0; i < m; ++i){
LL a,b,c; scanf("%lld%lld%lld",&a,&b,&c);
addEdge(a,b,c);
}
LL ans = 0;
Dijkstra(s, 0);
for(int i = 1; i <= n; ++i) ans+= d[i];
Dijkstra(s, 1);
for(int i = 1; i <= n; ++i) ans+= d[i];
printf("%lld\n",ans);
}
fclose(stdin);
return 0;
}