问你从1到其它点得所有最短路之和 与 其他点到1得所有最短路之和 得总和
思路很明确就是两次最短路,翻转一次地图就好了
一开始就是两次spfa之间处理好数据得更新管理就好
vector结构体数组存储边得数据
dis存储最短路径
vis表示i是否在队列中
id与cnt来链式前向星
需要仔细考虑得不仅仅是spfa算法了,而是开头和中间得跟新优化处理,该初始化的得初始化,初始化成什么值还得清楚
所以后来我就想用引用和数组指针来做,觉得得快一点吧,因为我用空间换了时间,新一个reedge
vector结构体数组,在输入的时候存储反向边,对应的还有reid,recnt
初始化方面不用考虑太多了,需要做的就是函数得参数多了,而这没什么麻烦得
一开始得code
#include <iostream> #include <queue> #include <string.h> #include <vector> #include <cstdio> #define inf 0x3f3f3f3f using namespace std; const int maxn = 1e6 + 1e2; struct node { int to,cost,pre; node(int t,int c,int p):to(t),cost(c),pre(p){} node(){} }; vector<node> edge; queue<int>q; int dis[maxn]; int vis[maxn]; int line[maxn][3]; int id[maxn],cnt; void add(int from,int to,int cost) { edge.push_back(node(to,cost,id[from])); id[from] = cnt++; } void init(int n) { for(int i = 1;i <= n;i++) { dis[i] = inf; vis[i] = 0; } edge.clear(); cnt = 0; memset(id,-1,sizeof(id)); } void spfa(int s,int n) { vis[s] = 1,dis[s] = 0; while(q.size())q.pop(); q.push(s); while(q.size()) { int now = q.front();q.pop();vis[now] = 0; for(int i = id[now];~i;i = edge[i].pre) { int to = edge[i].to; int cost = edge[i].cost; if(dis[to] > dis[now] + cost) { dis[to] = dis[now] + cost; if(!vis[to]) { q.push(to); vis[to] = 1; } } } } } int main() { int t,n,m; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); init(n); int a,b,x; for(int i = 0;i < m;i++) { scanf("%d%d%d",&line[i][0],&line[i][1],&line[i][2]); add(line[i][0],line[i][1],line[i][2]); } spfa(1,n); long long ans = 0; for(int i = 1;i <= n;i++) { ans += dis[i]; dis[i] = inf; vis[i] = 0; } cnt = 0; memset(id,-1,sizeof(id)); edge.clear(); for(int i = 0;i < m;i++) { add(line[i][1],line[i][0],line[i][2]); } spfa(1,n); for(int i = 1;i <= n;i++) { ans += dis[i]; } printf("%lld ",ans); } return 0; }
后来的
#include <iostream> #include <queue> #include <string.h> #include <vector> #include <cstdio> #define inf 0x3f3f3f3f using namespace std; const int maxn = 1e6 + 1e2; struct node { int to,cost,pre; node(int t,int c,int p):to(t),cost(c),pre(p){} node(){} }; vector<node> edge,reedge; queue<int>q; int dis[maxn]; int vis[maxn]; int id[maxn],cnt; int reid[maxn],recnt; void add(int from,int to,int cost,vector<node> &line,int *p,int &num) { line.push_back(node(to,cost,p[from])); p[from] = num++; } void init(int n) { for(int i = 1;i <= n;i++) { dis[i] = inf; vis[i] = 0; } edge.clear(); reedge.clear(); cnt = 0; recnt = 0; memset(id,-1,sizeof(id)); memset(reid,-1,sizeof(reid)); } void spfa(int s,int n,vector<node> &line,int *p) { vis[s] = 1,dis[s] = 0; while(q.size())q.pop(); q.push(s); while(q.size()) { int now = q.front();q.pop();vis[now] = 0; for(int i = p[now];~i;i = line[i].pre) { //cout<<i<<endl; int to = line[i].to; int cost = line[i].cost; if(dis[to] > dis[now] + cost) { dis[to] = dis[now] + cost; if(!vis[to]) { q.push(to); vis[to] = 1; } } } } } int main() { int t,n,m; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); init(n); int a,b,x; for(int i = 0;i < m;i++) { scanf("%d%d%d",&a,&b,&x); add(a,b,x,edge,id,cnt); add(b,a,x,reedge,reid,recnt); } spfa(1,n,edge,id); long long ans = 0; for(int i = 1;i <= n;i++) { ans += dis[i]; dis[i] = inf; vis[i] = 0; } spfa(1,n,reedge,reid); for(int i = 1;i <= n;i++) { ans += dis[i]; } printf("%lld ",ans); } return 0; }
让我i最不解得是后者竟然没有前者快,而且花了两倍得空间,我觉得可能是引用得问题吧~~其实我也不清楚嘞~