题意:给你一个有向图,多次询问从一个点到另一个点字典序最小的路径上第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的更多相关文章

  1. Codeforces Round #436 (Div. 2)【A、B、C、D、E】

    Codeforces Round #436 (Div. 2) 敲出一身冷汗...感觉自己宛如智障:( codeforces 864 A. Fair Game[水] 题意:已知n为偶数,有n张卡片,每张 ...

  2. Codeforces Round #485 (Div. 2) F. AND Graph

    Codeforces Round #485 (Div. 2) F. AND Graph 题目连接: http://codeforces.com/contest/987/problem/F Descri ...

  3. Codeforces Round #486 (Div. 3) F. Rain and Umbrellas

    Codeforces Round #486 (Div. 3) F. Rain and Umbrellas 题目连接: http://codeforces.com/group/T0ITBvoeEx/co ...

  4. Codeforces Round #501 (Div. 3) F. Bracket Substring

    题目链接 Codeforces Round #501 (Div. 3) F. Bracket Substring 题解 官方题解 http://codeforces.com/blog/entry/60 ...

  5. Codeforces Round #499 (Div. 1) F. Tree

    Codeforces Round #499 (Div. 1) F. Tree 题目链接 \(\rm CodeForces\):https://codeforces.com/contest/1010/p ...

  6. 水题 Codeforces Round #308 (Div. 2) A. Vanya and Table

    题目传送门 /* 水题:读懂题目就能做 */ #include <cstdio> #include <iostream> #include <algorithm> ...

  7. 水题 Codeforces Round #105 (Div. 2) B. Escape

    题目传送门 /* 水题:这题唯一要注意的是要用double,princess可能在一个小时之内被dragon赶上 */ #include <cstdio> #include <alg ...

  8. 水题 Codeforces Round #302 (Div. 2) A Set of Strings

    题目传送门 /* 题意:一个字符串分割成k段,每段开头字母不相同 水题:记录每个字母出现的次数,每一次分割把首字母的次数降为0,最后一段直接全部输出 */ #include <cstdio> ...

  9. 水题 Codeforces Round #299 (Div. 2) A. Tavas and Nafas

    题目传送门 /* 很简单的水题,晚上累了,刷刷水题开心一下:) */ #include <bits/stdc++.h> using namespace std; ][] = {" ...

随机推荐

  1. ReentrantLock源码(一)

    一.简介. ReentrantLock 是一个互斥锁,在基本行为和机制上与synchonized一样,只不过synchonized用方法和声明访问了隐式的锁监视器,但是ReentrantLock 做了 ...

  2. awk命令学习(1)

    awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大.简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各 ...

  3. IIS7配置rewriter

    遇到的问题就是rewriter不起效果冲IIS6迁移过来的.最后发现是Framework 4.0的原因!记录处理方式为: 一. <configSections> <section n ...

  4. Vue系列之 => 动画

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  5. hdu2262 高斯消元

    题目:有一个地图,一个人从某个点出发,问走到花园的期望步数为多少 设某点的期望步数为Ei. 那么目标的Ei=0. Ei=(Enext1+Enext2……Enextk)/k+1. 为什么是这个公式 因为 ...

  6. Sitecore详细安装(包含sitecore安装过程截图)

    一.到Sitecore 官网下载安装包 1)浏览器中输入https://dev.sitecore.net/Downloads/Sitecore_Experience_Platform.aspx 2)安 ...

  7. [博客迁移]探索Windows Azure 监控和自动伸缩系列3 - 启用Azure监控扩展收集自定义监控数据

    上一篇我们介绍了获取Azure的监控指标和监控数据: http://www.cnblogs.com/teld/p/5113376.html 本篇我们继续:监控虚拟机的自定义性能计数器. 随着我们应用规 ...

  8. 用 hashcat 破解 WIFI WPA2破解

    首先用CDlinux系统进行抓包,CDlinux抓包我就不详细说明 到这里可以查看如何安装CDlinux http://jingyan.baidu.com/article/7f766daf5173a9 ...

  9. 10 分钟速成 Python3

    Python 是由吉多·范罗苏姆(Guido Van Rossum)在 90 年代早期设计. 它是如今最常用的编程语言之一.它的语法简洁且优美,几乎就是可执行的伪代码. 注意:这篇教程是基于 Pyth ...

  10. Qt 之 模态、非模态、半模态窗口的介绍及 实现QDialog的exec()方法

    一.简述 先简单介绍一下模态与非模态对话框. 模态对话框 简单一点讲就是在弹出模态对话框时,除了该对话框整个应用程序窗口都无法接受用户响应,处于等待状态,直到模态对话框被关闭.这时一般需要点击对话框中 ...