题目链接
题目大意
求 1->2,2->3…n-1->n的最短路之和
题目思路
显然这题没什么优化的方法,先只能一次一次求,但是其实后面仔细想想只需要n/2次最短路即可。因为你跑 2 的时候 可以把 1->2 和2->3的都算出来。就当复习一下dij
代码
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int maxn=1e3+5;
int t,n,m,cnt,u,v,w,head[maxn],dis[maxn];
ll ans;//注意ans为ll
struct node{
int to,next,w;
}e[maxn*20];//双向边
void add(int u ,int v,int w){
e[++cnt].to=v;
e[cnt].w=w;
e[cnt].next=head[u];
head[u]=cnt;
}
void init(){
memset(head,0,sizeof(head));
memset(e,0,sizeof(e));
cnt=0,ans=0;
}
void dij(int x){
priority_queue<pii,vector<pii>,greater<pii> > que;
memset(dis,0x3f,sizeof(dis));
dis[x]=0;
que.push({0,x});
while(!que.empty()){
int len=que.top().first;
int pos=que.top().second;
que.pop();
if(len<=dis[pos]){
for(int i=head[pos];i;i=e[i].next){
if(dis[e[i].to]>dis[pos]+e[i].w){
dis[e[i].to]=dis[pos]+e[i].w;
que.push({dis[e[i].to],e[i].to});
}
}
}
}
}
signed main(){
scanf("%d",&t);
while(t--){
init();
scanf("%d %d",&n,&m);
for(int i=1;i<=m;i++){
scanf("%d %d %d",&u,&v,&w);
add(u,v,w),add(v,u,w);
}
for(int i=2;i<=n;i=i+2){
dij(i);
if(i==n){
ans+=dis[i-1];
}else{
ans+=dis[i-1]+dis[i+1];
}
}
printf("%lld\n",ans);
}
return 0;
}