重庆城里有n个车站,m条双向公路连接其中的某些车站。每两个车站最多用一条公路连接,从任何一个车站出发都可以经过一条或者多条公路到达其他车站,但不同的路径需要花费的时间可能不同。在一条路径上花费的时间等于路径上所有公路需要的时间之和。
佳佳的家在车站1,他有五个亲戚,分别住在车站a,b,c,d,e。过年了,他需要从自己的家出发,拜访每个亲戚(顺序任意),给他们送去节日的祝福。怎样走,才需要最少的时间?
输入
第一行:n(n<=50,000),m(m<=100,000)为车站数目和公路的数目。
第二行:a,b,c,d,e,为五个亲戚所在车站编号(1<a,b,c,d,e<=n)。
以下m行,每行三个整数x,y,t(1<=x,y<=n,1<=t<=100),为公路连接的两个车站编号和时间。
输出
仅一行,包含一个整数T,为最少的总时间
样例输入
6 6
2 3 4 5 6
1 2 8
2 3 3
3 4 4
4 5 5
5 6 2
1 6 7
样例输出
21
【问题分析】
简单的最短路,每个点一遍SPFA就好啦
【解决问题】
点1以及abcde五个点一次SPFA计算出六个点间任意两点最短路+搜索
Tips:算了算时间复杂度在本机上测最后三个大的点是超时,然而,然而,然而,评测机上居然A了!……恩,肯定是我家电脑太慢了。当然,读入优化也是必要的。
【代码实现】
#include<cstdio> #include<cstring> #include<queue> using namespace std; const int A=50010,B=100000*2+10,inf=4e8; int n,m,sum,ans=inf,s; int x,y,z; int head[A],g[8][8],l[8]={1},dis[6][A],ex[6][A],bo[A]; int line[A],ss; struct edge{ int to,nxt,len; }e[B]; queue<int>q; void build(int from,int to,int len) { e[++sum].to=to; e[sum].nxt=head[from]; e[sum].len=len; head[from]=sum; } void SPFA(int t,int st) { for(int i=1;i<=n;++i)dis[t][i]=inf; dis[t][st]=0; q.push(st); while(!q.empty()) { int tmp=q.front(); q.pop(); ex[t][tmp]=0; for(int i=head[tmp];i;i=e[i].nxt) { if(e[i].len+dis[t][tmp]<dis[t][e[i].to]) { dis[t][e[i].to]=e[i].len+dis[t][tmp]; if(!ex[t][e[i].to]) { ex[t][e[i].to]=1; q.push(e[i].to); } } } } for(int i=t+1;i<=5;++i) g[t][i]=g[i][t]=dis[t][l[i]]; } bool check() { for(int i=1;i<=5;++i) if(!bo[i])return false; return true; } void search(int x) { for(int i=1;i<=5;++i) { if(!bo[i]) { bo[i]=1; s+=g[x][i]; if(check()) { if(s<ans)ans=s; } else search(i); bo[i]=0; s-=g[x][i]; } } } void read(int &x) { x=0; char ch=getchar(); while(ch>‘9‘||ch<‘0‘)ch=getchar(); while(ch>=‘0‘&&ch<=‘9‘) { x=x*10+ch-‘0‘; ch=getchar(); } } int main() { read(n); read(m); for(int i=1;i<=5;++i)read(l[i]); for(int i=1;i<=m;++i) { read(x); read(y); read(z); build(x,y,z); build(y,x,z); } for(int i=0;i<=5;++i) SPFA(i,l[i]); ans=inf; s=0; search(0); printf("%d\n",ans); return 0; }
时间: 2024-08-06 08:11:15