题目

描述

(样例都懒得发出来了)

题目大意

给你一个有向图,从111号点出发,绕一圈回来。这一圈中必须经过222号点。

问经过的最少的点数(不重复)。


思考历程

一看就觉得是一道神题。

然后仔细观察一下数据范围:范围好像很小似的。

于是我就果断地想到了网络流!

于是我拼命地往网络流的方向去想,可是最后还是没有出什么结果。

看着比赛即将结束,也不应该不拿分,于是打暴力!

然后我就很自然地打了个IDA*

枚举答案ansansans,由于每个点最多经过两次,222号点只会经过一次,那么路径的长度不大于2∗ans−12*ans-12∗ans−1

预处理两点间距离,于是估价函数就显而易见了。

结果……

啊?AC了!!!

数据真水啊!


正解

这题实际上是强大的DP做法。

设fi,jf_{i,j}fi,j​表示走路径j→1→ij \to 1 \to ij→1→i,所经过的最少的城市数目。

转移的时候就通过分别从两边延伸出去。

还有另外一条方程:fi,j←fj,i+dis(j,i)−1  (i≠j)f_{i,j} \leftarrow f_{j,i}+dis(j,i)-1\ \ (i\neq j)fi,j​←fj,i​+dis(j,i)−1  (i̸​=j)

fj,if_{j,i}fj,i​可以理解成路径i→1→ji\to 1\to ji→1→j,加上dis(j,i)dis(j,i)dis(j,i)之后就变成j→i→1→j→ij \to i \to 1 \to j \to ij→i→1→j→i(重复的不计)

相当于在现在的路径上添个环。

于是这个DP就有些神仙了。判重呢?怎么就没有判重了!

首先很容易证明不存在j→1→k→k→ij \to 1 \to k \to k \to ij→1→k→k→i这样的情况,因为这样显然不是最优的,一定会被覆盖。

那会不会出现点数算重复了的状况呢?对于这点,我的理解比较感性:一个点最多出现在路径中两次。其实路径可以看成一堆环拼在一起,这个出现两次的点能与111点形成一个环。上面的这条方程式就是应对这种状况。在计算的过程中,的确有可能出现算重的状况,总会出现一个正确的没有算重的状况,而这个正确的状况就会将它们所覆盖。

然后这个DP就好像是正确的了。

由于这个东西明显有后效性,所以用Dijsktra来转移就可以了。

还有一种方法是题解的(我没有打),也是DP。

设fi,jf_{i,j}fi,j​表示路径1→i→j→11 \to i \to j \to 11→i→j→1经过最小点数。

转移:fx,y←fi,j+dis(j,x)+dis(x,y)+dis(y,i)−1f_{x,y} \leftarrow f_{i,j}+dis(j,x)+dis(x,y)+dis(y,i)-1fx,y​←fi,j​+dis(j,x)+dis(x,y)+dis(y,i)−1

这个方程其实比较好懂,不就是在i→ji\to ji→j这一段上强安上一个环嘛!

用类似上面的思想来分析,这个也是对的。

就理解成用将一堆环连在一起。

当然,由于这题的垃圾数据,其它方法过的也有很多。

好好打暴力就也可以过……


代码

using namespace std;
#include <cstdio>
#include <cstring>
#include <algorithm>
inline bool getmin(int &a,int b){return a>b?a=b:0;}
#define N 110
#define M 210
int n,m;
bool e[N][N];
int dis[N][N];
int f[N][N];
struct Node{
int x,y,s;
} h[1000001];
int nh;
inline bool cmph(const Node &son,const Node &fa){
return son.s>fa.s;
}
int main(){
scanf("%d%d",&n,&m);
memset(dis,63,sizeof dis);
for (int i=1;i<=m;++i){
int u,v;
scanf("%d%d",&u,&v);
u--,v--;
dis[u][v]=e[u][v]=1;
}
for (int k=0;k<n;++k)
for (int i=0;i<n;++i)
for (int j=0;j<n;++j)
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
memset(f,63,sizeof f);
f[0][0]=1;
h[nh++]={0,0,1};
while (nh){
Node top=h[0];
pop_heap(h,h+nh--,cmph);
if (f[top.x][top.y]<top.s)
continue;
if (top.x!=top.y)
getmin(f[top.x][top.y],f[top.y][top.x]+dis[top.y][top.x]-1);
for (int i=0;i<n;++i)
if (e[top.x][i] && getmin(f[i][top.y],f[top.x][top.y]+(i!=top.y))){
h[nh]={i,top.y,f[i][top.y]};
push_heap(h,h+ ++nh,cmph);
}
for (int i=0;i<n;++i)
if (e[i][top.y] && getmin(f[top.x][i],f[top.x][top.y]+(i!=top.x))){
h[nh]={top.x,i,f[top.x][i]};
push_heap(h,h+ ++nh,cmph);
}
}
printf("%d\n",f[1][1]);
return 0;
}

这题的代码是没有必要注解的,isn’t it?


总结

有时候我们会遇到一些需要判重的题目。

如果暴力方法时间复杂度超标,那我们可以考虑其他的思路。

想一想有没有什么方法可以在局部去重,并且计算准确的答案。

让这个答案覆盖掉其它不合法的东西。

[JZOJ3177] 【GDOI2013模拟5】安全监控的更多相关文章

  1. jzoj3156. 【GDOI2013模拟1】病毒传播

    题意: 村庄里有m个人,初始有一些人感染了病毒.如果第i个人的编号i满足,有一对(a,b)(a是初始病毒感染者编号,b为前一天的感染者编号)使\(a*b mod m =i\),则第i个人会感染病毒.每 ...

  2. 【GDOI2013模拟4】贴瓷砖

    题目 A镇的主街是由N个小写字母构成,镇长准备在上面贴瓷砖,瓷砖一共有M种,第i种上面有Li个小写字母,瓷砖不能旋转也不能被分割开来,瓷砖只能贴在跟它身上的字母完全一样的地方,允许瓷砖重叠,并且同一种 ...

  3. [JZOJ3168] 【GDOI2013模拟3】踢足球

    题目 描述 题目大意 有两个队伍,每个队伍各nnn人. 接到球的某个人会再下一刻随机地传给自己人.敌人和射门,射门有概率会中. 每次射门之后球权在对方111号选手. 某个队伍到了RRR分,或者总时间到 ...

  4. [JZOJ3167] 【GDOI2013模拟3】查税

    题目 描述 题目大意 维护一个有一次函数组成的序列 具体来说,对于位置xxx,现在的值为sx+zx∗(T−tx)s_x+z_x*(T-t_x)sx​+zx​∗(T−tx​) 有两个操作,修改某个位置上 ...

  5. [JZOJ3171] 【GDOI2013模拟4】重心

    题目 描述 题目大意 有一堆长为222的矩形,最下面的右端点横坐标为000. 每个矩形都有其固定的质量. 将这些矩形堆在一起,使得最右边的横坐标最大,并且满足它不会塌掉(满足物理学). 思考历程 首先 ...

  6. [JZOJ3187]【GDOI2013模拟8】的士

    题目 描述 题目大意 在一个数轴上,有些人要从某个点到达另一个点. 出租车从最左端出发,将所有人送到它们的目的地,最终到达最右边的点. 出租车只能做一个乘客,并且可以在图中将乘客丢下. 问最短时间. ...

  7. 不熟,不会,未a的题列表

    不熟: jzoj5968. 电竞选手(不知道公式如何得来) jzoj4877. [NOIP2016提高A组集训第10场11.8]力场护盾 (对向量不熟悉,不知道为什么结果要取反) jzoj4867. ...

  8. App开发:模拟服务器数据接口 - MockApi

    为了方便app开发过程中,不受服务器接口的限制,便于客户端功能的快速测试,可以在客户端实现一个模拟服务器数据接口的MockApi模块.本篇文章就尝试为使用gradle的android项目设计实现Moc ...

  9. 故障重现, JAVA进程内存不够时突然挂掉模拟

    背景,服务器上的一个JAVA服务进程突然挂掉,查看产生了崩溃日志,如下: # Set larger code cache with -XX:ReservedCodeCacheSize= # This ...

随机推荐

  1. Unicode与MultiByte之间的练习: Process Cleaner

    #include <cstdio> #include <cstring> #include <windows.h> #include <tlhelp32.h& ...

  2. SPSS缺失值得分析处理

    SPSS缺失值得分析处理 在资料收集的过程中,由于各种原因可能导致数据收集不全,就会产生缺失值,且这种情况往往无法避免.如果缺失值处理不当,就会导致分析结果精度降低,出现偏倚甚至是错误的理论,因此缺失 ...

  3. 安装mongo

    版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/weixin_40101530/articl ...

  4. Java & 架构硬核福利,速度上车!

    极客时间福利时间! 最近,栈长每周都会给大家带来极客时间的专栏拼团优惠,给错过优惠的朋友一个再次优惠上车的机会. <从0开始学架构>和<Java核心技术36讲>,这两个专栏很火 ...

  5. springboot整合thymeleaf手动渲染

    Thymeleaf手动渲染 为提高页面访问速度,可缓存html页面,客户端请求从缓存获取,获取不到再手动渲染 在spring4下 @Autowired ThymeleafViewResolver th ...

  6. javascript面向对象编程笔记(函数)

    第三章 函数 3.1 什么是函数 一般来说,函数声明通常由以下几部分组成: function子句 函数名称 函数所需参数 函数体 return子句.如果某个函数没有显示的返回值,默认它的返回值为und ...

  7. flutter setInitialRoute: 不生效

    概述 需要实现native跳转到flutter 指定的路由页面. iOS 工程中发现 FlutterViewController  setInitialRouter 无效,在我的需求里面是: 在iOS ...

  8. iOS_iPhone App自动化测试

    无线客户端的发展很快,特别针对是android和ios两款无线操作系统的客户端应用,相应的测试工具也应运而生,这里主要给大家介绍一些针对 iPhone App的自动化测试工具.          首先 ...

  9. eclipse导出说明文档

    选中项目--右键--Export--Java--Javadoc—Finish 1.为程序添加文档注释 2.选中项目--右键Export--Java--Javadoc--next, 3.next--在V ...

  10. (依赖注入框架:Ninject ) 一 手写依赖注入

    什么是依赖注入? 这里有一个场景:战士拿着刀去战斗: 刀: class Sword { public void Hit(string target) { Console.WriteLine($&quo ...