【做题】Codeforces Round #436 (Div. 2) F. Cities Excursions——图论+dfs
题意:给你一个有向图,多次询问从一个点到另一个点字典序最小的路径上第k个点。
考虑枚举每一个点作为汇点(记为i),计算出其他所有点到i的字典序最小的路径。(当然,枚举源点也是可行的)
首先,我们建一张反向图,从i开始dfs,以删去所有无法到达i的点。
然后,因为此时图上所有点都可以到达i,所以可以贪心地在从每一个点出发的边中只保留终点编号最小的边,而把其他边删除。
这样就可以保证路径是字典序最小的,并且从每个点到i的路径只有一条。
而题目中给出了这样一种情况:
- there are paths from sj to tj, but for every such path p there is another path q from sj to tj, such that pi > qi, where i is the minimum integer for which pi ≠ qi.
因此最后可能某些未被删去的点无法到达i,就需要从i开始再dfs一遍,以删去这些点。
在最后这次dfs的同时通过倍增记录路径(即祖先节点),以实现O(logn)地查询路径的第k个点。
时间复杂度O(n^2*logn+q*logn)。
#include <bits/stdc++.h>
#define travel(i,x,p) for(int i=p.fir[(x)];i;i=p.con[i].la)
#define nex(x,p) p.con[x].b
using namespace std;
const int N=,Q=;
struct edge{
int la,b;
};
struct graph{
edge con[N];
int tot,fir[N];
bool vis[N];
void init()
{
tot=;
memset(fir,,sizeof fir);
}
void add(int from,int to)
{
con[++tot].la=fir[from];
con[tot].b=to;
fir[from]=tot;
}
void dfs(int pos)
{
vis[pos]=;
for(int i=fir[pos];i;i=con[i].la)
{
if(!vis[con[i].b]) dfs(con[i].b);
}
}
}p1,p2,p3;
int n,m,q,anc[N][];
struct query{
int s,k,id;
};
vector<query>ask[N];
int ans[Q];
void exdfs(int pos)
{
p3.vis[pos]=;
for(int i=;i<=;i++)
anc[pos][i]=anc[anc[pos][i-]][i-];
for(int i=p3.fir[pos];i;i=p3.con[i].la)
{
anc[p3.con[i].b][]=pos;
exdfs(p3.con[i].b);
}
}
void doit(query tmp,int pos)
{
if(!p3.vis[tmp.s]) ans[tmp.id]=-;
else
{
tmp.k--;
pos=tmp.s;
for(int i=;i>=;i--)
{
if((<<i)<=tmp.k)
tmp.k-=(<<i),pos=anc[pos][i];
}
if(pos==) ans[tmp.id]=-;
else ans[tmp.id]=pos;
}
}
void solve(int pos)
{
memset(p2.vis,,sizeof p2.vis);
p2.dfs(pos);
p3.init();
int tmp;
for(int i=;i<=n;i++)
{
if(p2.vis[i]&&i!=pos)
{
tmp=n+;
travel(j,i,p1)
{
if(p2.vis[nex(j,p1)]&&nex(j,p1)<tmp)
tmp=nex(j,p1);
}
if(tmp!=n+) p3.add(tmp,i);
}
}
memset(p3.vis,,sizeof p3.vis);
memset(anc,,sizeof(anc));
exdfs(pos);
for(int i=;i<(int)ask[pos].size();i++)
{
doit(ask[pos][i],pos);
}
}
int main()
{
int from,to;
scanf("%d%d%d",&n,&m,&q);
for(int i=;i<=m;i++)
{
scanf("%d%d",&from,&to);
p1.add(from,to);
p2.add(to,from);
}
int x,y,k;
for(int i=;i<=q;i++)
{
scanf("%d%d%d",&x,&y,&k);
ask[y].push_back((query){x,k,i});
}
for(int i=;i<=n;i++)
solve(i);
for(int i=;i<=q;i++)
printf("%d\n",ans[i]);
return ;
}
小结:在诸如最小字典序路径和其他问题中,可以通过预处理以保证贪心的正确性。
【做题】Codeforces Round #436 (Div. 2) F. Cities Excursions——图论+dfs的更多相关文章
- Codeforces Round #436 (Div. 2)【A、B、C、D、E】
Codeforces Round #436 (Div. 2) 敲出一身冷汗...感觉自己宛如智障:( codeforces 864 A. Fair Game[水] 题意:已知n为偶数,有n张卡片,每张 ...
- Codeforces Round #485 (Div. 2) F. AND Graph
Codeforces Round #485 (Div. 2) F. AND Graph 题目连接: http://codeforces.com/contest/987/problem/F Descri ...
- Codeforces Round #486 (Div. 3) F. Rain and Umbrellas
Codeforces Round #486 (Div. 3) F. Rain and Umbrellas 题目连接: http://codeforces.com/group/T0ITBvoeEx/co ...
- Codeforces Round #501 (Div. 3) F. Bracket Substring
题目链接 Codeforces Round #501 (Div. 3) F. Bracket Substring 题解 官方题解 http://codeforces.com/blog/entry/60 ...
- Codeforces Round #499 (Div. 1) F. Tree
Codeforces Round #499 (Div. 1) F. Tree 题目链接 \(\rm CodeForces\):https://codeforces.com/contest/1010/p ...
- 水题 Codeforces Round #308 (Div. 2) A. Vanya and Table
题目传送门 /* 水题:读懂题目就能做 */ #include <cstdio> #include <iostream> #include <algorithm> ...
- 水题 Codeforces Round #105 (Div. 2) B. Escape
题目传送门 /* 水题:这题唯一要注意的是要用double,princess可能在一个小时之内被dragon赶上 */ #include <cstdio> #include <alg ...
- 水题 Codeforces Round #302 (Div. 2) A Set of Strings
题目传送门 /* 题意:一个字符串分割成k段,每段开头字母不相同 水题:记录每个字母出现的次数,每一次分割把首字母的次数降为0,最后一段直接全部输出 */ #include <cstdio> ...
- 水题 Codeforces Round #299 (Div. 2) A. Tavas and Nafas
题目传送门 /* 很简单的水题,晚上累了,刷刷水题开心一下:) */ #include <bits/stdc++.h> using namespace std; ][] = {" ...
随机推荐
- Oracle / PLSQL函数 - DECODE
1.DECODE( expression , search , result [, search , result]... [, default] ) 参数说明: expression : 表中的某一 ...
- Yii2开发小技巧
工作中或多或少会用到的关于 Yii2 的小技巧的一个总结,包括model.controller.view或者配置文件的一些写法. 模型相关 获取查询SQL $query = User::find()- ...
- Python - 2. Built-in Collection Data Types
From: http://interactivepython.org/courselib/static/pythonds/Introduction/GettingStartedwithData.htm ...
- copy on write,代理模式
StringBuilder 内部用了代理的技术实现, 是可变字符串的代理 .net设计模式实例之代理模式(Proxy Pattern) 一.代理模式简介(Brief Introduction) 代理模 ...
- 【Hbase学习之二】Hbase 搭建
环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 jdk8 hadoop-3.1.1 hbase-2.1.3 一.单机模 ...
- Java锁详解
http://blog.csdn.net/pzasdq/article/details/53128331 http://blog.csdn.net/truelove12358/article/deta ...
- SpringMVC七种参数绑定简单介绍
a. 默认支持的类型: httpServletRequest, httpservletresponse, httpsession, model 看自己需要, 如果需要用就加 ...
- Python+OpenCV图像处理(三)—— Numpy数组操作图片
一.改变图片每个像素点每个通道的灰度值 (一) 代码如下: #遍历访问图片每个像素点,并修改相应的RGB import cv2 as cv def access_pixels(image): prin ...
- 怎样从外网访问内网Oracle数据库?
本地安装了一个Oracle数据库,只能在局域网内访问到,怎样从外网也能访问到本地的Oracle数据库呢?本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Oracle数据库 默认安装的Or ...
- ES6知识整理(10)--class的继承
(这是es6的第10篇文章.说真的这样的总结之后虽然直观了许多,但是消耗的时间有点长,或许是知识比较复杂的原因吧) 类的继承 有个A类,B类继承A类,那B类实例就可以使用A类实例的所以属性和方法.不包 ...