题意:给你一个有向图,多次询问从一个点到另一个点字典序最小的路径上第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. kali linux wifi破解(aircrack)

    需要一个能监听的网卡 airmon-ng start wlan0(監聽網卡) airmon-ng check kill(清除其他有影响的環境) airodump-ng mon0 (掃描附近wifi) ...

  2. sqlserver清除缓存,记录查询时间

    文章来至:https://www.cnblogs.com/50614090/p/4001464.html --1. 将当前数据库的全部脏页写入磁盘.“脏页”是已输入缓存区高速缓存且已修改但尚未写入磁盘 ...

  3. pymysql 数据库操控

    模块安装 pip install pymysql 执行sql语句 import pymysql #添加数据 conn = pymysql.connect(host='127.0.0.1', port= ...

  4. Knowing is not enough; we must apply. Willing is not enough; we must do.

    Knowing is not enough; we must apply. Willing is not enough; we must do. 仅限于知道是不够的,我们必须去实践:单纯的希望是不够的 ...

  5. restful的特点

    1. 资源(Resources) REST的名称”表现层状态转化”中,省略了主语.”表现层”其实指的是”资源”(Resources)的”表现层”.                所谓”资源”,就是网络 ...

  6. java实现 HTTP/HTTPS请求绕过证书检测代码实现

    java实现 HTTP/HTTPS请求绕过证书检测代码实现 1.开发需求 需要实现在服务端发起HTTP/HTTPS请求,访问其他程序资源. 2.URLConnection和HTTPClient的比较 ...

  7. windows.onload和body的onload属性的区别

    关于windows.onload和body的onload属性的区别网上有些说法说的也不太统一,现在系统说下: 先看共同点: 都是body内容体加载结束执行: window.onload 内部方式可以 ...

  8. JustOJ1500: 蛇行矩阵

    题目链接:https://oj.ismdeep.com/problem?id=1500 题目描述 蛇形矩阵是由1开始的自然数依次排列成的一个矩阵上三角形. 输入 本题有多组数据,每组数据由一个正整数N ...

  9. Python词云分析

    import jieba from matplotlib import pyplot as plt from wordcloud import WordCloud from PIL import Im ...

  10. Android开发常见错误汇总

    [错误信息] [2011-01-19 16:39:10 - ApiDemos] WARNING: Application does not specify an API level requireme ...