[Solution] JZOJ3470 最短路

题面

Description

给定一个n个点m条边的有向图,有k个标记点,要求从规定的起点按任意顺序经过所有标记点到达规定的终点,问最短的距离是多少。

Input

第一行5个整数n、m、k、s、t,表示点个数、边条数、标记点个数、起点编号、终点编号。

接下来m行每行3个整数x、y、z,表示有一条从x到y的长为z的有向边。

接下来k行每行一个整数表示标记点编号。

Output

输出一个整数,表示最短距离,若没有方案可行输出-1。

Sample Input

3 3 2 1 1

1 2 1

2 3 1

3 1 1

2

3

Sample Output

3

【样例解释】

路径为1->2->3->1。

Data Constraint

20%的数据n<=10。

50%的数据n<=1000。

另有20%的数据k=0。

100%的数据n<=50000,m<=100000,0<=k<=10,1<=z<=5000。




分割线




解题思路

这个题很显然是一个最短路的问题,主要分为一下步骤

Step1:预处理出起点终点和k个关键点之间的最短路

Step2:因为看到了0<=k<=10所以可以暴力搜路过点顺序的全排列

Step3:不要忘记剪枝

复杂度O(knlogn+k!)

具体见Code


Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<vector>
#define maxn 50006
#define inf 0x3f3f3f3f3f3f3f3f
#define ll long long
using namespace std;
ll dis[maxn];
ll book[maxn];
ll f[15][15];
ll n,m,k,p,q;
struct Edge{
ll t,w,nxt;
}edge[maxn*2];
ll head[maxn],tot=0;
ll kk[20];
ll ans=inf,num=0;
priority_queue< pair<ll,ll> > hep;
ll gmin(ll a,ll b){return a<b?a:b;}
void add(ll st,ll to,ll we){edge[tot].t=to;edge[tot].w=we;edge[tot].nxt=head[st];head[st]=tot;tot++;}
void init(){
memset(head,-1,sizeof(head));
scanf("%lld %lld %lld %lld %lld",&n,&m,&k,&p,&q);
for(ll i=1;i<=m;i++){
ll a,b,c;scanf("%lld %lld %lld",&a,&b,&c);
add(a,b,c);
if(b==q)
add(a,n+1,c);
}
for(ll i=1;i<=k;i++)
scanf("%lld",kk+i);
kk[0]=p;kk[k+1]=n+1;
return;
}
void dij(ll s){
ll ss=s;
s=kk[s];
memset(dis,0x3f,sizeof(dis));
memset(book,0,sizeof(book));
while(!hep.empty()) hep.pop();
dis[s]=0;
hep.push(make_pair(0-dis[s],s));
while(!hep.empty()){
ll ns=hep.top().second;
hep.pop();
if(book[ns]) continue;
book[ns]=1;
for(ll i=head[ns];i!=-1;i=edge[i].nxt){
ll t=edge[i].t;
if(dis[t]>dis[ns]+edge[i].w){
dis[t]=dis[ns]+edge[i].w;
hep.push(make_pair(0-dis[t],t));
}
}
}
for(ll i=0;i<=k+1;i++)
f[ss][i]=dis[kk[i]];
return;
}
void dfs(ll dep,ll st){
if(num>=ans) return;
if(dep==k){
if(f[st][k+1]!=inf){
num+=f[st][k+1];
ans=gmin(ans,num);
num-=f[st][k+1];
}return;
}
for(ll i=1;i<=k;i++) if(!book[i])
if(f[st][i]!=inf){
book[i]=1;
num+=f[st][i];
dfs(dep+1,i);
num-=f[st][i];
book[i]=0;
}
}
void solve(){
for(ll i=0;i<=k;i++)
dij(i);
if(k==0)
if(f[0][1]!=inf){
printf("%lld\n",f[0][1]);return;
}
else{
printf("-1\n");return;
}
memset(book,0,sizeof(book));
for(ll i=1;i<=k;i++)if(f[0][i]!=inf){
memset(book,0,sizeof(book));
num+=f[0][i];
book[i]=1;
dfs(1,i);
book[i]=0;
num-=f[0][i];
}
if(ans==inf)
printf("-1\n");
else
printf("%lld\n",ans);
return;
}
int main(){
init();
solve();
return 0;
}

[Solution] JZOJ3470 最短路的更多相关文章

  1. P1266 速度限制 (最短路,图论)

    题目链接 Solution 在最短路转移的时候在队列或者堆中记录状态为 \(f[u][v]\) 代表上一个节点为 \(u\) ,速度为 \(v\) . 然后按部就班转移即可... Code #incl ...

  2. [SinGuLaRiTy] 复习模板-图论

    [SinGuLaRiTy-1041] Copyright (c) SinGuLaRiTy 2017. All Rights Reserved. 计算树的直径 //方法:任选一个点作为起点进行一次BFS ...

  3. [AtCoder arc090E]Avoiding Collision

    Description 题库链接 给出一张 \(N\) 个节点, \(M\) 条边的无向图,给出起点 \(S\) 和终点 \(T\) .询问两个人分别从 \(S\) 和 \(T\) 出发,走最短路不相 ...

  4. DP&图论 DAY 5 上午

    DP&图论  DAY 5  上午 POJ 1125 Stockbroker Grapevine 有 N 个股票经济人可以互相传递消息,他们之间存在一些单向的通信路径.现在有一个消息要由某个人开 ...

  5. [bzoj3694]最短路

    Description 给出一个$n$个点$m$条边的无向图,$n$个点的编号从$1-n$,定义源点为$1$. 定义最短路树如下:从源点$1$经过边集$T$到任意一点$i$有且仅有一条路径,且这条路径 ...

  6. 【BZOJ-4456】旅行者 分治 + 最短路

    4456: [Zjoi2016]旅行者 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 254  Solved: 162[Submit][Status] ...

  7. 【BZOJ-4289】Tax 最短路 + 技巧建图

    4289: PA2012 Tax Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 168  Solved: 69[Submit][Status][Dis ...

  8. 【BZOJ-2007】海拔 最小割 (平面图转对偶图 + 最短路)

    2007: [Noi2010]海拔 Time Limit: 20 Sec  Memory Limit: 552 MBSubmit: 2095  Solved: 1002[Submit][Status] ...

  9. 【BZOJ-3931】网络吞吐量 最短路 + 最大流

    3931: [CQOI2015]网络吞吐量 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1228  Solved: 524[Submit][Stat ...

随机推荐

  1. 使用睿云智合开源 Breeze 工具部署 Kubernetes v1.12.3 高可用集群

    一.Breeze简介 Breeze 项目是深圳睿云智合所开源的Kubernetes 图形化部署工具,大大简化了Kubernetes 部署的步骤,其最大亮点在于支持全离线环境的部署,且不需要FQ获取 G ...

  2. java面试多线程问题

    Java多线程面试问题 1. 进程和线程之间有什么不同? 一个进程是一个独立(self contained)的运行环境,它可以被看作一个程序或者一个应用.而线程是在进程中执行的一个任务.Java运行环 ...

  3. JAVA多线程17个问题

    1.Thread 类中的start() 和 run() 方法有什么区别? Thread.start()方法(native)启动线程,使之进入就绪状态,当cpu分配时间该线程时,由JVM调度执行run( ...

  4. Python中xlrd和xlwt模块使用方法

    本文主要介绍可操作excel文件的xlrd.xlwt模块.其中xlrd模块实现对excel文件内容读取,xlwt模块实现对excel文件的写入. 安装xlrd和xlwt模块 xlrd和xlwt模块不是 ...

  5. python学习笔记_week26

    note 一.CMDB -采集资产 -API -后台管理 -资产列表(CURD) -业务线列表(CURD) -用户列表(CURD) -组列表(CURD) ... ===>简单<=== 公共 ...

  6. RestExpress response中addHeader 导致stackOverflow

    问题描述: 最近在项目使用中要在restExpress的header中增加一个键值对,同事在使用的时候没有对header的value进行非空判断,于是在测试环境测试的时候就出现了一个异常

  7. LNMP 目录限制

    php.ini 未设置open_basedir和user_ini.filename,但user_ini.filename默认为.user.ini,所以会使用网站根目录下的.user.ini文件来控制 ...

  8. jeecg开源项目的IDEA的部署

    JEECG采用了SpringMVC + Hibernate + Minidao(类Mybatis) + Easyui(UI库)+ Jquery + Boostrap + Ehcache + Redis ...

  9. 安装Caffe纪实

    第一章 引言 在ubuntu16.04安装caffe,几乎折腾了一个月终于成功;做一文章做纪要,以便日后查阅.总体得出的要点是:首先,每操作一步,必须知道如何检验操作的正确性;笔者的多次失误是因为配置 ...

  10. MYSQL性能优化(2)

    Insert语句优化 1.  多行并为一个语句  insert into table values (行1),(行2),........... 2. 使用中间内存队列, 逻辑是立马执行插入,其他数据放 ...