洛谷P5764 [CQOI2005]新年好 题解
题目链接:P5764 [CQOI2005]新年好
题意:从 $1$ 号结点出发,要访问其他 $5$ 个结点,顺序随意,访问一个结点后不用返回
注意到 $5! = O(1)$
那我们可以在 $1$ 和其他 $5$ 个点跑一下dijkstra,然后枚举所有可能的顺序即可
这里给出了两种枚举方式,分别为dfs
和next_permutation()
实测(C++14 O2)后者快30ms
左右,不过均可轻松通过此题
我才不会说我是因为先写后者没调出来才有的这篇题解呢 QAQ
dfs
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define INF (int)(5e10+233)
#define gc() getchar()
#define pc(a) putchar(a)
#define MAXN (int)(5e4+5)
template<typename T>void read(T &k)
{
char ch=gc();T x=0,f=1;
while(!isdigit(ch)){if(ch=='-')f=-1;ch=gc();}
while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=gc();}
k=x*f;
}
template<typename T>void write(T k)
{
if(k<0){k=-k;pc('-');}
if(k>9)write(k/10);
pc(k%10+'0');
}
struct Edge
{
int u,v,w,next;
}e[MAXN<<2];
struct node
{
int u,dis;
bool operator<(const node &o)const
{
return dis>o.dis;
}
};
int n,m,a[15],d[8][MAXN],vis[MAXN];
int head[MAXN],pos=1,ans=INF,used[MAXN];
void addEdge(int u,int v,int w)
{
e[pos]={u,v,w,head[u]};
head[u]=pos++;
}
priority_queue<node> q;
void dijkstra(int st,int idx)
{
for(int i=1; i<=n; i++)
d[idx][i]=INF,vis[i]=0;
q.push({st,0});d[idx][st]=0;
while(!q.empty())
{
int u=q.top().u;q.pop();
if(vis[u])
continue;
vis[u]=1;
for(int i=head[u]; i; i=e[i].next)
{
int v=e[i].v;
if(d[idx][v]>d[idx][u]+e[i].w)
{
d[idx][v]=d[idx][u]+e[i].w;
if(!vis[v])
q.push({v,d[idx][v]});
}
}
}
}
void dfs(int dep,int now,int last)
{
if(now>ans)return;
if(dep==5)
{
ans=min(ans,now);
return;
}
for(int i=1; i<=5; i++)
if(!used[i])
{
used[i]=1;
dfs(dep+1,now+d[last][a[i]],i);
used[i]=0;
}
}
signed main()
{
read(n);read(m);
for(int i=1; i<=5; i++)
read(a[i]);
for(int i=1,u,v,w; i<=m; i++)
{
read(u);read(v);read(w);
addEdge(u,v,w);addEdge(v,u,w);
}
dijkstra(1,0);
for(int i=1; i<=5; i++)
dijkstra(a[i],i);
dfs(0,0,0);
write(ans);pc('\n');
return 0;
}
next_permutation()
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define INF (int)(5e10+233)
#define gc() getchar()
#define pc(a) putchar(a)
#define MAXN (int)(5e4+5)
template<typename T>void read(T &k)
{
char ch=gc();T x=0,f=1;
while(!isdigit(ch)){if(ch=='-')f=-1;ch=gc();}
while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=gc();}
k=x*f;
}
template<typename T>void write(T k)
{
if(k<0){k=-k;pc('-');}
if(k>9)write(k/10);
pc(k%10+'0');
}
struct Edge
{
int u,v,w,next;
}e[MAXN<<2];
struct node
{
int u,dis;
bool operator<(const node &o)const
{
return dis>o.dis;
}
};
int n,m,a[15],b[15],d[8][MAXN],vis[MAXN];
int head[MAXN],pos=1,ans=INF;
unordered_map<int,int>id;
void addEdge(int u,int v,int w)
{
e[pos]={u,v,w,head[u]};
head[u]=pos++;
}
priority_queue<node> q;
void dijkstra(int st,int idx)
{
for(int i=1; i<=n; i++)
d[idx][i]=INF,vis[i]=0;
q.push({st,0});d[idx][st]=0;
while(!q.empty())
{
int u=q.top().u;q.pop();
if(vis[u])
continue;
vis[u]=1;
for(int i=head[u]; i; i=e[i].next)
{
int v=e[i].v;
if(d[idx][v]>d[idx][u]+e[i].w)
{
d[idx][v]=d[idx][u]+e[i].w;
if(!vis[v])
q.push({v,d[idx][v]});
}
}
}
}
int f(int x,int y){return d[id[x]][y];}
int sum()
{
int res=f(1,a[b[1]]);
for(int i=2; i<=5; i++)
res+=f(a[b[i-1]],a[b[i]]);
return res;
}
signed main()
{
read(n);read(m);
for(int i=1; i<=5; i++)
read(a[i]);
for(int i=1,u,v,w; i<=m; i++)
{
read(u);read(v);read(w);
addEdge(u,v,w);addEdge(v,u,w);
}
dijkstra(1,id[1]=0);
for(int i=1; i<=5; i++)
dijkstra(a[i],id[a[i]]=i);
for(int i=1; i<=5; i++)b[i]=i;
do
{
ans=min(ans,sum());
}while(next_permutation(b+1,b+1+5));
write(ans);pc('\n');
return 0;
}