Codeforces Round #436 (Div. 2)
2017-09-28 21:00
447 查看
这套题…
前两题出的太慢了,A题题目看的太慢,然后单纯模拟,wa了两发,然后重写了一下过了。
BC没有什么问题。
D题,emmm,是先减再换,不小心先换再减了,又贡献了几发==
E题,有限制条件的01背包,在这片博客的最后有分析
F题。参考了代码
开始感觉就是个离线操作,将所有询问都存下来,将相同起点的一起询问(询问就是dfs),然后时间复杂度为n*m。
dfs开始想的比较单纯,从起点开始走字典序最小的那条路,在遍历的点中,如果是要查询的终点的话,就把答案记下来。如果遇到环的话全部跳出,没有遍历到的询问就都为-1.
然后WA了,因为首先,如果有环的话,不一定要直接跳出,有些点还要遍历,比如这个图
1 2
2 3
3 4
4 5
2 5
如果查1 5 2的话,结果就是-1。但是1到5并不经过那个环。所以说,这个就是要判断1个点到另一个的路径上有没有环
如果有环的话,回到这个环的起点,继续dfs,那么可以用tarjan
前两题出的太慢了,A题题目看的太慢,然后单纯模拟,wa了两发,然后重写了一下过了。
BC没有什么问题。
D题,emmm,是先减再换,不小心先换再减了,又贡献了几发==
E题,有限制条件的01背包,在这片博客的最后有分析
F题。参考了代码
开始感觉就是个离线操作,将所有询问都存下来,将相同起点的一起询问(询问就是dfs),然后时间复杂度为n*m。
dfs开始想的比较单纯,从起点开始走字典序最小的那条路,在遍历的点中,如果是要查询的终点的话,就把答案记下来。如果遇到环的话全部跳出,没有遍历到的询问就都为-1.
然后WA了,因为首先,如果有环的话,不一定要直接跳出,有些点还要遍历,比如这个图
1 2
2 3
3 4
4 5
2 5
如果查1 5 2的话,结果就是-1。但是1到5并不经过那个环。所以说,这个就是要判断1个点到另一个的路径上有没有环
如果有环的话,回到这个环的起点,继续dfs,那么可以用tarjan
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <cmath> #include <vector> #include <set> using namespace std; #define ll long long #define mem(a,b) memset(a,b,sizeof(a)) const int inf =1e6; const int maxn = 3010; int st[maxn],dfn[maxn],res[400010],low[maxn],vis_st[maxn]; struct node { int id,from,to,k; node(){} node(int a,int d,int b,int c){ id=a,from=d,to=b,k=c; } }; node qs[400010]; vector<int> v[maxn]; vector<node> Q[maxn]; bool cmp(node a1,node a2) { if(a1.from!=a2.from) return a1.from<a2.from; else return a1.to<a2.to; } int top=0,tot=0; void Tarjan(int u,int ok) { st[++top]=u; dfn[u]=++tot; low[u]=inf;//这个开始设为比较大的数,之后如果low比dfn小的话,证明之间有环 vis_st[u]=1; if(ok) for(int i=0;i<Q[u].size();i++) if(Q[u][i].k<=top) res[Q[u][i].id]=st[Q[u][i].k]; for(int i=0;i<v[u].size();i++) { int t=v[u][i]; if(!dfn[t]) { Tarjan(t,ok&&dfn[u]<low[u]); low[u]=min(low[u],low[t]); } else if(vis_st[t]) low[u]=min(low[u],dfn[t]); } vis_st[u]=0; top--; } int main() { int n,m,q; scanf("%d %d %d",&n,&m,&q); memset(res,-1,sizeof(res)); for(int i=0;i<m;i++) { int a,b; scanf("%d %d",&a,&b); v[a].push_back(b); } for(int i=1;i<=n;i++) sort(v[i].begin(),v[i].end()); for(int i=1;i<=q;i++) { int a,b,k; scanf("%d %d %d",&a,&b,&k); qs[i]=node(i,a,b,k); } sort(qs+1,qs+q+1,cmp); for(int i=1;i<=q;i++) { Q[qs[i].to].push_back(qs[i]); if(qs[i].from!=qs[i+1].from) { mem(st,0);mem(dfn,0);mem(vis_st,0);mem(low,0); tot=0,top=0; Tarjan(qs[i].from,1); for(int j=1;j<=n;j++) Q[j].clear(); } } for(int i=1;i<=q;i++) printf("%d\n",res[i]); return 0; }
相关文章推荐
- 宽高均为百分比的DIV,水平垂直居中
- Wunder Fund Round 2016 (Div. 1 + Div. 2 combined) E. Robot Arm 线段树
- JS动态添加div,然后在div中添加元素
- DIV里面的图片水平与垂直居中的方法
- Codeforces Round #422 (Div. 2)
- Codeforces Round #455 (Div. 2)
- 大家需要掌握的 html下SPAN和DIV的区别
- div+css布局遇到的一些问题和解决方法
- JS onmousemove鼠标移动坐标接龙DIV效果实例
- 让DIV的滚动条自动滚动到最底部 - 4种方法
- Codeforces Round #306 (Div. 2) 550A Two Substrings
- 点击自动显示/隐藏DIV代码。(简单实用)
- DIV常见任务(上) —常规任务(显示滚动条/隐藏div/禁止事件冒泡等等)
- DIV+CSS布局时, DIV的高度和宽度特性
- 地图上显示div点位
- css+div页面布局
- div+css常用资料
- html页面js实现多个div定时轮流出现
- div+css居中
- Codeforces Round #252 (Div. 2) 441B. Valera and Fruits