Cq OI 2005 新年好
简要分析:
- 本题要求经过一定的点的最短路
- 类似题目:孤岛营救问题
- 易得,从 i 点出发,经过 k 点 ,到达 j 点的最短路, 一定是从 i 到 k 的最短路加上从 k 到 j 的最短路
- 证明 :假设:从 i 点出发,经过 k 点 ,到达 j 点的最短路,不是从 i 到 k 的最短路加上从 k 到 j 的最短路
- 则应存在 路径 E1(i->k)+E2(k->j)<E1min+E2min 易证得假设不成立
- 枚举 从每个亲戚家出发到达其它车站所需时间
- 再枚举每种路径所需时间
- 时间复杂度(5*M log M+5^5) 可以接受
注意事项
- 本题是无向图,注意建图和建边
- 注意每次dijkstra都要重新预处理
具体代码
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<vector> #include<queue> using namespace std; const int inf=2147483637,Max_N=50010,Max_M=100010; typedef pair<int,int>node; struct Edge { int dis,to,next; } E[Max_M*2];//注意是无向边 int Head[Max_N],Dis[6][Max_N],num_Edge,vis[Max_N]; inline int Read(void)//快读 { char ch=0; int w=0,x=0; while(!isdigit(ch)) w|=ch=='-',ch=getchar(); while(isdigit(ch)) x=x*10+(ch^48),ch=getchar(); return w?-x:x; } inline void Add_Edge(int from,int to,int dis)//建边 { E[++num_Edge].dis =dis; E[num_Edge].to =to; E[num_Edge].next =Head[from]; Head[from]=num_Edge; } int N,M,T[6],S,Ans=inf; inline void Dijkstra(int num)//求从T[num]点出发到达每点的最短路 { priority_queue <node,vector<node>,greater<node> >Q; for(int i=1; i<=N; ++i) Dis[num][i]=(i==S?0:inf),vis[i]=0; Q.push(make_pair(0,S)) ; while(!Q.empty() ) { int u=Q.top() .second; Q.pop() ; if(vis[u])continue; else vis[u]=1; for(int i=Head[u]; i; i=E[i].next ) { int v=E[i].to ; if(Dis[num][v]>Dis[num][u]+E[i].dis ) { Dis[num][v]=Dis[num][u]+E[i].dis ; if(!vis[v]) Q.push(make_pair(Dis[num][v],v)) ; } } } } int main(void) { N=Read(),M=Read(); for(int i=1; i<=5; ++i) T[i]=Read(); for(int i=1; i<=M; ++i) { int u=Read(),v=Read(),d=Read(); Add_Edge(u,v,d);//注意是无向边 Add_Edge(v,u,d); } T[0]=1; for(int i=0; i<=5; ++i) { S=T[i]; Dijkstra(i); } memset(vis,0,sizeof(vis)); for(int t1=1; t1<=5; ++t1)//枚举路径 { vis[t1]=1; for(int t2=1; t2<=5; ++t2) { if(!vis[t2]) { vis[t2]=1; for(int t3=1; t3<=5; ++t3) { if(!vis[t3]) { vis[t3]=1; for(int t4=1; t4<=5; ++t4) { if(!vis[t4]) { vis[t4]=1; for(int t5=1; t5<=5; ++t5) { if(!vis[t5]) { Ans=min(Ans,Dis[0][T[t1]]+Dis[t1][T[t2]]+Dis[t2][T[t3]]+Dis[t3][T[t4]]+Dis[t4][T[t5]]); } } vis[t4]=0; } } vis[t3]=0; } } vis[t2]=0; } } vis[t1]=0; } printf("%d\n",Ans); return 0; }