重庆城里有n个车站,m条双向公路连接其中的某些站。每两个车站最多用一条公路直接相连,从任何一个车站出发都可以经过一条或多条公路到达其它车站,但不同的路径需要花费的时间可能不同。在一条路径上花费的时间等于路径上所有公路需要的时间和。
佳佳的家在车站1,他有五个亲戚,分别住在车站a、b、c、d、e。过年了,他需要从自己的家出发,拜访每个亲戚(顺序任意),给他们送去节日的祝福。怎样走,才需要最少的时间?
用最短路算法,求出5个点分别的距离,和1到五个点的距离,
然后枚举完事
#include<cstdio> #include<cstdlib> #include<cstring> #include<queue> using namespace std; int n,m; const int N=5e4+3,M=1e5+3; int tot,head[N]; struct node { int v,w,nx; }e[M<<1]; void add(int u,int v,int w) { e[++tot].v =v,e[tot].w =w,e[tot].nx =head[u],head[u]=tot; e[++tot].v =u,e[tot].w =w,e[tot].nx =head[v],head[v]=tot; } inline int read() { int x=0;char c=getchar(); while(c<'0' || c>'9') c=getchar(); while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-'0',c=getchar(); return x; } int dis[N]; bool in[N]; int pt[6],dd[6][6]; struct nd { int v; bool operator < (const nd & o) const { return dis[v] > dis[o.v]; } nd(int vv) { v=vv; } nd(){} }; priority_queue <nd> q; void dijk(int st,int k) { while(!q.empty() ) q.pop() ; memset(dis,0x3f,sizeof(dis)); memset(in,false,sizeof(in)); dis[st]=0,q.push(nd(st)); while(!q.empty() ) { int nw=q.top() .v;q.pop() ; for(int i=head[nw];i;i=e[i].nx ) { int nx=e[i].v ; if(dis[nx]>dis[nw]+e[i].w ) { dis[nx]=dis[nw]+e[i].w ; if(!in[nx]) in[nx]=true,q.push(nd(nx)); } } in[nw]=false; } for(int i=1;i<=5;i++) dd[k][i]=dis[pt[i]]; } bool us[6];int ans=1<<30; void dfs(int cnt,int sum,int pre) { if(sum>ans) return ; if(cnt==5) { ans=min(ans,sum); return ; } for(int i=1;i<=5;i++) { if(us[i]) continue; us[i]=true; dfs(cnt+1,sum+dd[pre][i],i); us[i]=false; } } int main() { n=read(),m=read(); pt[0]=1; for(int i=1;i<=5;i++) scanf("%d",&pt[i]); int u,v,w; for(int i=1;i<=m;i++) { u=read(),v=read(),w=read(); add(u,v,w); } for(int i=0;i<=5;i++) dijk(pt[i],i); dfs(0,0,0); printf("%d\n",ans); return 0; }