新年好
题目描述
佳佳在节点1,需要访问5个亲戚(顺序任意),求访问时的最短路(不用回来)。
思路
考虑到这道题n、m都不算大,亲戚个数也不多,我们可以暴力队节点1和每一个目标节点做一次Dijkstra,求出这几个点和其他点的最短路后,暴力枚举每个亲戚的排列顺序,对所有方案取最小值即可。
代码
#include <bits/stdc++.h> using namespace std; const int N=50005,M=1e5+10,INF=1e8; int head[N],nxt[M<<1],to[M<<1],w[M<<1],tot; int dis[N][6],ans=INF,n,m; int goal[6]; bool vis[N],used[10]; void add_edge(int x,int y,int v) { nxt[++tot]=head[x]; head[x]=tot; to[tot]=y; w[tot]=v; } void Dijkstra(int s,int cnt) { priority_queue<pair<int,int> >q; for(int i=1;i<=n;i++)dis[i][cnt]=INF; memset(vis,0,sizeof(vis)); dis[s][cnt]=0;q.push(make_pair(0,s)); while(!q.empty()) { int u=q.top().second;q.pop(); if(vis[u])continue ; vis[u]=1; for(int i=head[u];i;i=nxt[i]) { int v=to[i]; if(dis[v][cnt]>dis[u][cnt]+w[i]) { dis[v][cnt]=dis[u][cnt]+w[i]; q.push(make_pair(-dis[v][cnt],v)); } } } } void dfs(int k,int st,int sum) { // cout<<k<<' '<<st<<' '<<sum<<endl; if(k==5) { ans=min(ans,sum); return ; } for(int i=1;i<6;i++) if(!used[i]) { used[i]=1; dfs(k+1,i,sum+dis[goal[i]][st]); used[i]=0; } } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=5;i++) scanf("%d",&goal[i]); for(int i=1;i<=m;i++) { int x,y,z; scanf("%d%d%d",&x,&y,&z); add_edge(x,y,z); add_edge(y,x,z); } Dijkstra(1,0); for(int i=1;i<=5;i++) Dijkstra(goal[i],i); dfs(0,0,0); printf("%d",ans); return 0; }