洛谷P5764 [CQOI2005]新年好 题解
链接:https://www.luogu.com.cn/problem/P5764
题目:
重庆城里有 nn 个车站,mm 条双向公路连接其中的某些车站。每两个车站最多用一条公路连接,从任何一个车站出发都可以经过一条或者多条公路到达其他车站,但不同的路径需要花费的时间可能不同。在一条路径上花费的时间等于路径上所有公路需要的时间之和。
佳佳的家在车站 11,他有五个亲戚,分别住在车站 a,b,c,d,ea,b,c,d,e。过年了,他需要从自己的家出发,拜访每个亲戚(顺序任意),给他们送去节日的祝福。怎样走,才需要最少的时间?
输入格式
第一行:n,mn,m,分别为车站数目和公路的数目。
第二行:a,b,c,d,ea,b,c,d,e,分别为五个亲戚所在车站编号。
以下 mm 行,每行三个整数 x,y,tx,y,t,为公路连接的两个车站编号和时间。
输出格式
仅一行,包含一个整数 TT,为最少的总时间。保证 T\le 10^9T≤109。
输入输出样例
输入 #1
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
输出 #1
21
说明/提示
对于 40\%40% 的数据,有 1≤n≤5001≤n≤500,1≤m≤20001≤m≤2000。
对于 100\%100% 的数据,有 1≤n≤500001≤n≤50000,1≤m≤1000001≤m≤100000,1\le a,b,c,d,e≤n1≤a,b,c,d,e≤n,1≤x,y≤n1≤x,y≤n,1≤t≤100001≤t≤10000。
分析
看到题目就知道是老SPAF了,不过我喜欢用DJ
代码如下:
#include<bits/stdc++.h> #define X 60000 using namespace std; int n,m,a[10],u,v,w; int dis[10][X],ans=0x3fffffff; bool vis[X],vis2[10]; struct node{ int v,value; bool operator <(const node &a) const {return this->value>a.value;} }; vector<node>ve[X];//vector大法好!! priority_queue<node>q;//优先队列,不用说了 void Empty(){while(q.size())q.pop();} void dij(int p){//dj的堆优化不用谈了 Empty(); memset(vis,false,sizeof vis); for(int i=1;i<=n;++i)dis[p][i]=0x3fffffff; dis[p][a[p]]=0; q.push((node){a[p],0}); while(q.size()){ node now=q.top(); q.pop(); int where=now.v; if(vis[where])continue; vis[where]=1; for(unsigned long i=0;i<ve[where].size();++i) if(dis[p][where]+ve[where][i].value<dis[p][ve[where][i].v]) dis[p][ve[where][i].v]=dis[p][where]+ve[where][i].value,q.push((node){ve[where][i].v,dis[p][ve[where][i].v]});//自己细细品味一下 } } void dfs(int p,int num,int now){//由于亲戚有好几个,所以要dfs所有路,求出最短的一个 if(p==5){ ans=min(ans,num);//记录答案 return; } for(int i=1;i<=5;i++){ if(!vis2[i]){ vis2[i]=true; dfs(p+1,dis[now][a[i]]+num,i); vis2[i]=false; } } } int main() { scanf("%d%d",&n,&m);//推荐使用快读 for(int i=1;i<=5;i++)scanf("%d",&a[i]); a[0]=1; for(int i=1;i<=m;++i){ scanf("%d%d%d",&u,&v,&w); ve[u].push_back((node){v,w}); ve[v].push_back((node){u,w}); } for(int i=0;i<=5;i++) dij(i); dfs(0,0,0); printf("%d",ans); }
快读:
inline int read(){ int f=1,res; char c; while((c=getchar())<'0'||c>'9') if(c=='-')f=-1; res=c-48; while((c=getchar())>='0'&&c<='9') res=res*10+c-48; return res*f; }
完了
重庆真是个好地方