新年好qaq

68 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 23 天,点击查看活动详情

[CQOI2005]新年好

题目描述

重庆城里有 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,为最少的总时间。保证 T109T\le 10^9

样例 #1

样例输入 #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\% 的数据,有 1n5001≤n≤5001m20001≤m≤2000

对于 100%100\% 的数据,有 1n500001≤n≤500001m1000001≤m≤1000001a,b,c,d,en1\le a,b,c,d,e≤n1x,yn1≤x,y≤n1t100001≤t≤10000

分析

这是一道比较简单的dfs+dijkstra(),自从被卡了之后就再也不想用spfa了,先预处理一下1和abcde6个点到各个点的最小值,也就是跑6遍dijkstra(),然后dfs全排列遍历查询看哪一种走的方式时间最少。

代码

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <map>
#include <set>
#include <iomanip>
#include <cmath>
#include <unordered_map>
#include <stack>
#include <queue>
#define ll long long
#define lowbit(x) x&(-x)
using namespace std;
typedef pair<int,ll> PII;
typedef pair<string,int> PSI;
typedef stack<int> stk;
ll gcd(ll x,ll y){
    return y?gcd(y,x%y):x;
}
ll qmi(ll x,ll y,int mod){
    ll res=1;
    while(y){if(y&1) res=res*x%mod;y>>=1;x=x*x%mod;}
    return res;
}
const int N=400010;
int n,m;
int id[6];
bool st[N];
int idx=0,w[N],e[N],ne[N],h[N];
int dist[6][N];
int cnt=0;
inline void add(int a,int b,int c){
    e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++;
}
inline void dijkstra(int x){
    dist[cnt][x]=0;
    memset(st,false,sizeof st);
    priority_queue<PII,vector<PII>,greater<PII>> heap;
    heap.push({dist[cnt][x],x});
    while(heap.size()){
        PII t=heap.top();
        heap.pop();
        int ver=t.second,distance=t.first;
        if(st[ver]) continue;
        st[ver]=true;
        for(int i=h[ver];~i;i=ne[i]){
            int j=e[i];
            if(dist[cnt][j]>distance+w[i]){
                dist[cnt][j]=distance+w[i];
                heap.push({dist[cnt][j],j});
            }
        }
    }
}
int dfs(int u,int start,int distance){
    if(u==6){
        return distance;
    }
    int res=0x3f3f3f3f;
    for(int i=1;i<6;i++){
       if(!st[i]){
           st[i]=true;
           res=min(res,dfs(u+1,i,distance+dist[start][id[i]]));
           st[i]=false;
       }
    }
    return res;
}
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    memset(h,-1,sizeof h); 
    memset(dist,0x3f,sizeof dist);
    cin>>n>>m;
    id[0]=1;
    for(int i=1;i<6;i++){
        cin>>id[i];
    }
    while(m--){
        int a,b,c;
        cin>>a>>b>>c;
        add(a,b,c),add(b,a,c);
    }
    for(int i=0;i<6;i++){
        dijkstra(id[i]);
        cnt++;
    }
    memset(st,false,sizeof st);
    cout<<dfs(1,0,0)<<"\n";
    return 0;
}