AcWing1135新年好(dfs+dijkstra)

题目地址https://www.acwing.com/problem/content/description/1137/

题目描述

重庆城里有 n 个车站,mm条 双向 公路连接其中的某些车站。

每两个车站最多用一条公路连接,从任何一个车站出发都可以经过一条或者多条公路到达其他车站,但不同的路径需要花费的时间可能不同。

在一条路径上花费的时间等于路径上所有公路需要的时间之和。

佳佳的家在车站 1,他有五个亲戚,分别住在车站 a,b,c,d,e

过年了,他需要从自己的家出发,拜访每个亲戚(顺序任意),给他们送去节日的祝福。

怎样走,才需要最少的时间?

输入格式

第一行:包含两个整数 n,m,分别表示车站数目和公路数目。

第二行:包含五个整数 a,b,c,d,e分别表示五个亲戚所在车站编号。

以下 m 行,每行三个整数 x,y,t表示公路连接的两个车站编号和时间。

输出格式

输出仅一行,包含一个整数 T,表示最少的总时间。

数据范围

1n50000
1m1e5
1<a,b,c,d,en
1x,yn
1t100

题解:这道题是dfs+dijkstra,我们可以分别求出1,a,b,c,d,e到其余点的最段距离,那么剩下的,只需要枚举这六个点的先后顺序,枚举的时候,因为之前dijkstra将所有的距离都算出来了,那么这一步枚举的复杂度也只是O(5!)

AC代码

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
const int N=50010,M=1e5+10;
#define P pair<int,int> 
struct node{
    int from,to,next,dis;
}edge[M*2];
int head[N],cnt,dis[6][N],fl[6]={0},ans=0x3f3f3f3f,a[6];

void dfs(int x,int s,int dep){
    if(dep==5){//只有最后一次才能回到1
        ans=min(ans,s);
        return ;
    }
    for(int i=1;i<=5;i++){
        if(!fl[i]) {
            fl[i]=1;
            dfs(i,s+dis[x][a[i]],dep+1);
            fl[i]=0;
        }
    }
    return ;
}

void addedge(int u,int v,int w){
    cnt++;
    edge[cnt].from=u;
    edge[cnt].to=v;
    edge[cnt].dis=w;
    edge[cnt].next=head[u];
    head[u]=cnt;
}


void dijkstra(int s,int k){
    memset(dis[k],0x3f,sizeof(dis[k]));
    int p[N]={0};
    priority_queue<P,vector<P>,greater<P> >q;
    q.push(make_pair(0,s));
    dis[k][s]=0;
    while(!q.empty()){
        P now=q.top();q.pop();
        if(p[now.second]) continue;
        p[now.second]=1;
        int w=now.first,v=now.second;
        for(int i=head[v];~i;i=edge[i].next){
            if(dis[k][edge[i].to]>dis[k][edge[i].from]+edge[i].dis){
                dis[k][edge[i].to]=dis[k][edge[i].from]+edge[i].dis;
                q.push(make_pair(dis[k][edge[i].to],edge[i].to));
            }
        }
    }
}

int main(){
    int n,m;cin>>n>>m;
    a[0]=1;
    memset(head,-1,sizeof(head));
    for(int i=1;i<=5;i++) cin>>a[i];
    for(int i=1,u,v,w;i<=m;i++){
        scanf("%d%d%d",&u,&v,&w);
        addedge(u,v,w);
        addedge(v,u,w);
    }
    for(int i=0;i<=5;i++){
        dijkstra(a[i],i);
    }
    dfs(0,0,0);
    cout<<ans;
    return 0;
}

写于:2020/9/5 14:51

posted @ 2020-09-05 14:52  白菜茄子  阅读(177)  评论(0编辑  收藏  举报