洛谷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^9T109。

输入输出样例

输入 #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≤5001n500,1≤m≤20001m2000。

对于 100\%100% 的数据,有 1≤n≤500001n50000,1≤m≤1000001m100000,1\le a,b,c,d,e≤n1a,b,c,d,en,1≤x,y≤n1x,yn,1≤t≤100001t10000。

分析

看到题目就知道是老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;
}

 

完了

重庆真是个好地方


 

posted @ 2020-06-23 16:47  Nakiri_Ayame_suki  阅读(423)  评论(0编辑  收藏  举报