[POI2007]ATR-Tourist Attractions [TPLY]
[POI2007]ATR-Tourist Attractions
题目链接(https://www.luogu.org/problemnew/show/P3451)
这种稠密图还是建议你不要跑spfa,你跑dijkstra堆优化会快很多
要看原图戳我(左下角被洛谷图标遮住了)
题意
题目给你的意思就是
求1到n的
必须经过一些点(2→k+1)
而且过这些点还要讲先后顺序
的最短路长度
解题
首先看到k<=20
它这是告诉你
对于这k个必须经过的点
你怎么暴力怎么搞
所以我们对这k个点每个点单元最短路(dijkstra)一下,求出他们到所有点的距离。dis[i][j]表示由i出发到j的距离
然后是处理先后关系。我们建立一个数组r[i],r[i]的值,表示到达第i个点之前,必须停留的点的状压集合,1为必经,0为无所谓(因为k<=20所以可以状压)
接着就是状压DP。这里f[i][j]表示当前状态集合为i(1为停留过,0为没有),目前停留在j的最短路径。
转移就是普通状压dp套路,从0到(1<<k-1)[全都有] 枚举状态,找到一个集合中存在的点和一个集合中不存在的点,如果当前状态满足这个不在集合内的点的r[i](也就是经过它之前必须经过的点都经过了)那么就进行转移。
初始状态,f设为INF,如果一个点i在停留之前不需要在任何点停留,那么f[1][i]=dis[1][i],f[0][1]=0
几点注意(长者的经验教训)
1.当k=0时直接跑最短路不然会WA第六个点
2.INF不能开太大(第三个点会爆成负数)
3.数组要卡空间,不然要么RE要么MLE
4.如果数组太大最好不用memset,最好自己给数组赋值,这样会快很多
5.注意位运算的先后顺序,能打括号就打括号。
代码
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#define rg register int
#define RG register
#define ll long long
#define il inline
#define INF 1000000000 // INF 不要太大会飞起
#define mk make_pair
using namespace std;
typedef pair <int,int> P;
il int gi()
{
    rg x=0,o=0;RG char ch=getchar();
    while((ch!='-')&&(ch<'0'||ch>'9')) ch=getchar();
    if(ch=='-') o=1,ch=getchar();
    while('0'<=ch&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    return o?-x:x;
}
struct Edge{int to,nxt,w;}e[300001];
int Ehead[30001],Ecnt=1;
il void Eadd(rg u,rg v,rg w)
{
    e[Ecnt]=(Edge){v,Ehead[u],w};
    Ehead[u]=Ecnt++;
    e[Ecnt]=(Edge){u,Ehead[v],w};
    Ehead[v]=Ecnt++;
}
int n,m,k,g;
int r[32],dis[32][30001];
priority_queue <P,vector<P>,greater<P> > Q;
il void dijkstra(rg rt)
{
    for(rg i=1;i<=n;++i) dis[rt][i]=INF;
    while(!Q.empty()) Q.pop();
    Q.push(mk(0,rt));dis[rt][rt]=0;
    while(!Q.empty())
    {
        rg u=Q.top().second;Q.pop();
        for(rg i=Ehead[u];i;i=e[i].nxt)
        {
            rg v=e[i].to;
            if(dis[rt][v]>dis[rt][u]+e[i].w)
            {
                dis[rt][v]=dis[rt][u]+e[i].w;
                Q.push(mk(dis[rt][v],v));
            }
        }
    }
}
// dijkstra 无vis数组
int f[1<<20][25],Ans=INF;
int a,b,u,v,w;
int main()
{
    n=gi(),m=gi(),k=gi();
    for(rg i=1;i<=m;++i)
    {
        u=gi(),v=gi(),w=gi();
        Eadd(u,v,w);
    }
    if(!k)
    {
    	dijkstra(1);
    	printf("%d",dis[1][n]);
    	return 0;
    } //不加这个判断第6个点会WA
    g=gi();
    for(rg i=1;i<=g;++i)
    {
        a=gi(),b=gi();
        r[b] |= (1<<(a-2));
    }
    for(rg i=1;i<=k+1;++i)  dijkstra(i);
    for(rg i=0;i<=(1<<k)-1;++i)
     for(rg j=1;j<=k+1;++j)
      f[i][j]=INF;
    // 数组大就尽量不用memset
    f[0][1]=0;
    for(rg i=2;i<=k+1;++i)
     if(!r[i])
      f[1<<(i-2)][i]=dis[1][i];
    for(rg i=1;i<=(1<<k)-1;++i)
     for(rg j=0;j<k;++j)
      if(i&(1<<j))
       for(rg l=0;l<k;++l)
        if( !(i&(1<<l)) && (i|r[l+2])==i )
         f[i|(1<<l)][l+2]=min(f[i|(1<<l)][l+2],f[i][j+2]+dis[j+2][l+2]);        
    for(rg i=2;i<=k+1;++i)
     Ans=min(Ans,f[(1<<k)-1][i]+dis[i][n]);
  	printf("%d",Ans);
    return 0;
}
[POI2007]ATR-Tourist Attractions [TPLY]的更多相关文章
- csp-s模拟48,49 Tourist Attractions,养花,画作题解
		题面:https://www.cnblogs.com/Juve/articles/11569010.html Tourist Attractions: 暴力当然是dfs四层 优化一下,固定两个点,答案 ... 
- [POI2007]Tourist Attractions
		题目大意: 给你一个$n(n\leq 2\times 10^4)$个点,$m(m\leq 2\times 10^5)$条边的带边权的连通图.其中有$k(k\leq 20)$个关键点.关键点之间有$g$ ... 
- LYDSY模拟赛day1 Tourist Attractions
		/* 假设路径是 a − b − c − d,考虑枚举中间这条边 b − c,计 算有多少可行的 a 和 d. 设 degx 表示点 x 的度数,那么边 b − c 对答案的贡献为 (degb − 1 ... 
- 解题:POI 2007 Tourist Attractions
		题面 事实上这份代码在洛谷过不去,因为好像要用到一些压缩空间的技巧,我并不想(hui)写(捂脸) 先预处理$1$到$k+1$这些点之间相互的最短路和它们到终点的最短路,并记录下每个点能够转移到时的状态 ... 
- 【JZOJ4857】Tourist Attractions(Bitset)
		题意:给定一个n个点的无向图,求这个图中有多少条长度为4的简单路径. n<=1500 思路: #include<map> #include<set> #include&l ... 
- [CSP-S模拟测试]:Tourist Attractions(简单图论+bitset)
		题目描述 在美丽的比特镇一共有$n$个景区,编号依次为$1$到$n$,它们之间通过若干条双向道路连接.$Byteasar$慕名来到了比特镇旅游,不过由于昂贵的门票费,他只能负担起$4$个景区的门票费. ... 
- 比特镇旅游(Tourist Attractions)【暴力+Bitset  附Bitset用法】
		Online Judge:NOIP2016十连测第一场 T2 Label:暴力,Bitset 题目描述 在美丽的比特镇一共有n个景区,编号依次为1到n,它们之间通过若干条双向道路连接. Byteasa ... 
- D. 旅游景点 Tourist Attractions  状压DP
		题目描述 FGD想从成都去上海旅游.在旅途中他希望经过一些城市并在那里欣赏风景,品尝风味小吃或者做其他的有趣的事情.经过这些城市的顺序不是完全随意的,比如说FGD 不希望在刚吃过一顿大餐之后立刻去下一 ... 
- 旅游景点 Tourist Attractions 题解
		题面在这里 再次破了纪录,连做了3天... 让我们从头来一点一点分析 1.预处理 先看题面,乍一看貌似是个图论题,有n个点m条边,给定一些必须经过的点和强制经过顺序,求一条最短路 我们发现n和m都比较 ... 
随机推荐
- ACE_TEST1.obj : error LNK2019: 无法解析的外部符号
			ACE_TEST1.obj : error LNK2019: 无法解析的外部符号 "int __cdecl ace_main_i(int,char * * const)" (?ac ... 
- centos7 网桥的配置
			centos7下配置网桥,两个步骤:1.新建网桥配置2.修改网卡配置 新建br0 网桥配置 在/etc/sysconfig/network-scripts/目录下新建ifcfg-br0,添加如下配置信 ... 
- dedecms判断当前页面是否为首页 织梦设置首页高亮
			做织梦网站导航栏时,我们一般需要设置当前栏目高亮显示,这个使用currentstyle就能直接实现,但是如果在首页时怎么让首页模块高亮呢? 织梦当前栏目高亮: <style>.hover{ ... 
- 教我徒弟Android开发入门(二)
			前言: 上一期实现了简单的QQ登录效果,这一期继续对上一期进行扩展 本期的知识点: Toast弹窗,三种方法实现按钮的点击事件监听 正文: Toast弹窗其实很简单,在Android Studio ... 
- object类的equals方法简介 & String类重写equals方法
			object类中equals方法源码如下所示 public boolean equals(Object obj) { return this == obj; } Object中的equals方法是直接 ... 
- 基于JDK1.8的HashMap分析
			HashMap的强大功能,相信大家都了解一二.之前看过HashMap的源代码,都是基于JDK1.6的,并且知其然不知其所以然,现在趁着寒假有时间,温故而知新.文章大概有以下几个方面: HashMap的 ... 
- ubuntu下boost编译安装
			ubuntu下boost编译安装 boost 安装 1.依赖安装 apt-get install mpi-default-dev libicu-dev python-dev python3-dev l ... 
- 5. 跟踪标记 (Trace Flag) 834, 845 对内存页行为的影响
			跟踪标记:834 功能: 在64位的windows环境下,为SQL Server开启这个跟踪标记,那么SQL Server 会使用大页(Large pages)为内存缓冲区(buffer pool)分 ... 
- 如何使用 OpenCV 打开摄像头获取图像数据?
			OpenCV 如何打开摄像头获取图像数据? 代码运行环境:Qt 5.9.1 msvc2015 32bit OpenCV 3.3.0 #include "include/opencv2/ope ... 
- hbase存储优化
			1.上面的2张图主要说明hbase的存储特点 (1).每个值(每条记录的每一个列的值)的存储,都完整的存储了rowkey.column family.column.版本(时间戳),以及该列的值. 这样 ... 
