NOIP 2015 Senior 2
来源:互联网 发布:愿我知一生为何 编辑:程序博客网 时间:2024/06/05 20:08
思路1:
可以把它看成一个n个点,n条边的图,问题转换为求一个最小环。由于只有n条边,求环等价于求结点数大于2的强连通分量。然后用Kosaraju算法写(不要问我为什么不用Tarjan= =):
#include <cstdio>#include <cstdlib>#include <cmath>#include <cstring>#include <iostream>#include <algorithm>#include <vector>#include <string>#include <stack>#include <queue>#include <deque>#include <map>#include <set>using std::cin;using std::cout;using std::endl;inline int readIn(){ int a; scanf("%d", &a); return a;}const int maxn = 200005;int n;int G[maxn];bool vis[maxn];std::vector<std::vector<int> > GT;std::stack<int> sequeue;int ans = -1;int temp;void dfsG(int from){ if(vis[from]) return; vis[from] = true; dfsG(G[from]); sequeue.push(from);}void dfsGT(int from){ if(vis[from]) return; vis[from] = true; temp++; for(int i = 0; i < GT[from].size(); i++) { dfsGT(GT[from][i]); }}void run(){ n = readIn(); GT.resize(n + 1); for(int i = 1; i <= n; i++) { G[i] = readIn(); GT[G[i]].push_back(i); } memset(vis, 0, sizeof(bool) * (n + 1)); for(int i = 1; i <= n; i++) { if(!vis[i]) dfsG(i); } memset(vis, 0, sizeof(bool) * (n + 1)); while(!sequeue.empty()) { int top = sequeue.top(); sequeue.pop(); if(vis[top]) continue; temp = 0; dfsGT(top); if(temp > 1 && (ans == -1 || temp < ans)) { ans = temp; } } printf("%d\n", ans);}int main(){ run(); return 0;}
这代码看上去一切正常对不对!可惜,在n=200000时,dfs不幸爆栈了。。。
预计得分:100 实际得分:90
思路2:其实这道题直接”dfs“的时候判断有没有重复经过点就好了,走的时候再记录一下步数。由于每个点只有一个出度,所以用循环模拟dfs,防止了爆栈的发生。
#include <cstdio>#include <cstdlib>#include <cmath>#include <cstring>#include <iostream>#include <algorithm>#include <vector>#include <string>#include <stack>#include <queue>#include <deque>#include <map>#include <set>using std::cin;using std::cout;using std::endl;inline int readIn(){ int a; scanf("%d", &a); return a;}const int maxn = 200005;int n;int G[maxn];bool vis[maxn];int step[maxn];int Index[maxn]; //只有当index相等时才能说明是在同一次搜索中搜到的,这时才能判断是不是找到了圈//若index不相等,则只是相当于重复访问了结点,应及时退出int count_;int ans = -1;void dfs(int from){ step[from] = 1; while(true) { vis[from] = true; Index[from] = count_; if(vis[G[from]] && step[G[from]] && Index[G[from]] == count_) //找到圈 { if(step[from] - step[G[from]] + 1 > 1 && (ans == -1 || ans > step[from] - step[G[from]] + 1)) { ans = step[from] - step[G[from]] + 1; } return; } else if(vis[G[from]]) return; else { step[G[from]] = step[from] + 1; from = G[from]; } }}void run(){ n = readIn(); for(int i = 1; i <= n; i++) { G[i] = readIn(); } for(int i = 1; i <= n; i++) { if(!vis[i]) { count_++; dfs(i); } } printf("%d\n", ans);}int main(){ run(); return 0;}
其中,还是要十分注意里面的细节,比如那个Index数组的使用和step数组的使用。想清楚再写,不然很容易写错。前9组数据还是有点弱,哪怕代码有点瑕疵都能过,但是第10组数据很强= =。
阅读全文
0 0
- NOIP 2015 Senior 2
- NOIP 2015 Senior 3
- NOIP 2015 Senior 5
- NOIP 2015 Senior 4
- NOIP 2015 Senior 6
- NOIP 2011 Senior 2
- NOIP 2012 Senior 2
- NOIP 2014 Senior 2
- NOIP 2013 Senior 2
- NOIP 2016 Senior 2
- NOIP 2009 Senior 1
- NOIP 2009 Senior 4
- NOIP 2009 Senior 3
- NOIP 2011 Senior 3
- NOIP 2011 Senior 4
- NOIP 2011 Senior 5
- NOIP 2011 Senior 6
- NOIP 2012 Senior 5
- datagridview第一列空白隐藏掉
- RANSAC
- 关于Arista DCS 7048交换机不支持ECN功能的说明
- Bokeh 添加注释
- 《Drools7.0.0.Final规则引擎教程》第3章 3.2 KIE概念&FACT对象
- NOIP 2015 Senior 2
- 字符串字符由小到大的排序输出
- iOScopy详解
- 根据省份编号获取该省下面的市和地区和省份
- mybatis与hibernate区别
- Java中输入/输出流体系中常用的流分类
- Oracle 创建 split 和 splitstr 函数
- 设计模式--观察者模式--Java实现
- 利用LFW对人脸识别模型进行精度评测