题意:在有向图中求起点到所有点的最短路径长度和所有点到起点的最短路径长度的总和。
思路:
1.起点到所有点的最短路径很好求,直接求单源最短路径即可。
2.所有点到起点的最短路径,如果我们把每一条边都反过来,那么再求一次单源最短路径即可。
注意:
1.poj上的数据超int了,需要用long long。
2.我用cin超时了。。。,换scanf就过了,唉cin还是少用啊。
3.poj 6000ms有点慢。。。
代码:
#include <iostream>
#include <cstdio>
#include <vector>
#include <queue>
using namespace std;
const long long inf = 1000000000005;
const int maxn = 1000005;
struct node{
int index;
int w;
node(int tindex, int tw){index = tindex; w = tw;}
bool operator < (const node &b) const{
return w > b.w;
}
};
struct edge{
int v;
int w;
edge(int tv, int tw){v = tv; w = tw;}
};
int n,m;
int x[maxn],y[maxn],wi[maxn];
long long dist[maxn]; //Dijkstra算法所需的数组
bool vis[maxn];
vector<edge> a[maxn]; //邻接矩阵
priority_queue<node> q;
void Input() {
int u,v,w;
scanf("%d%d",&n,&m);
for(int i = 1; i <= m; i++){
scanf("%d%d%d",&x[i],&y[i],&wi[i]);
}
}
void Dijkstra(){
for(int i = 1; i <= n; i++){
vis[i] = 0;
dist[i] = inf;
}
dist[1] = 0;
q.push(node(1,0));//初始节点入队
while(!q.empty()){
int u = q.top().index;
q.pop();
if(vis[u]) continue;
else vis[u] = 1;
for(int j = 0; j < a[u].size(); j++){
int v = a[u][j].v;
if(!vis[v] && dist[u] + a[u][j].w < dist[v]){
dist[v] = dist[u] + a[u][j].w;
q.push(node(v,dist[v]));
}
}
}
}
void Solve(){
long long sum = 0;
for(int i = 1; i <= n; i++) a[i].clear();
for(int i = 1; i <= m; i++) a[x[i]].push_back(edge(y[i],wi[i]));
Dijkstra();
for(int i = 1; i <= n; i++){
sum += dist[i];
}
for(int i = 1; i <= n; i++) a[i].clear();
for(int i = 1; i <= m; i++) a[y[i]].push_back(edge(x[i],wi[i]));
Dijkstra();
for(int i = 1; i <= n; i++){
sum += dist[i];
}
printf("%lld\n",sum);
}
int main(){
int t;
cin>>t;
while(t--){
Input();
Solve();
}
}