【问题描述】  
  
  下图表示一次街道赛跑的跑道。可以看出有一些路口(用 0 到 N 的整数标号),和连接这些路口的箭头。路口 0 是跑道的起点,路口 N 是跑道的终点。箭头表示单行街道。运动员们可以顺着街道从一个路口移动到另一个路口(只能按照箭头所指的方向)。当运动员处于路口位置时,他可以选择任意一条由这个路口引出的街道。
            

  上图有 10 个路口的跑道 一个良好的跑道具有如下几个特点:

  1)、每一个路口都可以由起点到达。 
  2)、从任意一个路口都可以到达终点。
  3)、终点不通往任何路口。 
  4)、运动员不必经过所有的路口来完成比赛。有些路口却是选择任意一条路线都必须到达的(称为“不可避免”的)。在上面的例子中,这些路口是 0,3,6,9。对于给出的良好的跑道,你的程序要确定“不可避免”的路口的集合,不包括起点和终点。

  假设比赛要分两天进行。为了达到这个目的,原来的跑道必须分为两个跑道,每天使用一个跑道。第一天,起点为路口 0,终点为一个“中间路口”;第二天,起点是那个中间路口,而终点为路口 N。

  对于给出的良好的跑道,你的程序要确定“中间路口”的集合。如果良好的跑道 C 可以被路口 S 分成两部分,这两部分都是良好的,并且 S 不同于起点也不同于终点,同时被分割的两个部分满足下列条件:

  1)、它们之间没有共同的街道

  2)、S 为它们唯一的公共点,并且 S 作为其中一个的终点和另外一个的起点。那么我们称 S 为“中间路口 ”。在例子中只有路口 3 是中间路口。(注: 其实简而言之就是说第二天除了中间路口无论怎么跑也跑不到第一天的路口上)

【输入格式】  
  
  包括一个良好的跑道,最多有 50 个路口,100 条单行道。 一共有 N+2 行,前面 N+1 行中第 i 行表示以编号为(i-1)的路口作为起点的街道,每个数字表示一个终点。行末用 -2 作为结束。最后一行只有一个数字 -1。

【输出格式】  
   
  你的程序要有两行输出: 
  第一行包括:跑道中“不可避免的”路口的数量,接着是这些路口的序号,序号按照升序排列。 
  第二行包括:跑道中“中间路口”的数量,接着是这些路口的序号,序号按照升序排列。

【输入样例】   
   
1 2 -2
3 -2
3 -2
5 4 -2
6 4 -2
6 -2
7 8 -2
9 -2
5 9 -2
-2
-1

【输出样例】  
   
2 3 6
1 3

【数据范围】  
   
  最多有 50 个路口,100 条单行道。

解题思路:根据题意,因为不可避免的路口是从起点到终点一定要经过的路口,所以要求不可避免的路口就可以枚举除起点和终点外的每个路口,将该路口删掉(假删除,用数组进行标记),看从起点能否走到终点,即进行一次DFS(或BFS)遍历,如果能走到,则该路口不是不可避免的路口,如果不能,则该路口就是不可避免的路口。接下来是求中间路口,因为中间路口将跑道分为两部分后,从中间路口出发和从起点出发经过的路口除了中间路口外是没有公共的,而分成两个跑道后从起点出发经过的路口在求不可避免的路口时已经标记过了,所以只需枚举除起点和终点外的每个路口,从该路口出发进行一次DFS(或BFS)遍历,标记出所能到达的路口,如果从起点出发经过的路口和从该路口出发经过的路口有相同的,则该路口不是中间路口,否则,该路口就是中间路口。

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<vector>
using namespace std;
const int maxn=55;
int N=0,x;
vector<int>g[maxn],ans1,ans2;
int vis1[maxn],vis2[maxn];
void DFS1(int i)
{vis1[i]=1;for(int k=0;k<g[i].size();k++){int j=g[i][k];if(vis1[j])  continue;DFS1(j);}
}
void DFS2(int i)
{vis2[i]=1;for(int k=0;k<g[i].size();k++){int j=g[i][k];if(vis2[j])  continue;DFS2(j);}
}
int main()
{freopen("48.in","r",stdin);//freopen("48.out","w",stdout);while(1){scanf("%d",&x);if(x==-1)  break;else if(x==-2)  N++;else {g[N].push_back(x);}}N--;int cnt1=0,cnt2=0;  //记录答案个数for(int i=1;i<N;i++){memset(vis1,0,sizeof(vis1));vis1[i]=1;  //将该路口假删除DFS1(0);if(vis1[N]==0)  //判断是否为不可避免的路口{cnt1++;ans1.push_back(i);}memset(vis2,0,sizeof(vis2));DFS2(i);int ok=1;  //判断是否为中间路口for(int j=0;j<=N;j++)if(vis1[j]==1 && vis2[j]==1 && j!=i)  //注意j!=i,因为在假删除时,令vis1[i]=1了,但从起点出发并不能到达第i个路口{ok=0;break;}if(ok==1){cnt2++;ans2.push_back(i);}}printf("%d ",cnt1);for(int k=0;k<ans1.size();k++)printf("%d ",ans1[k]);printf("\n");printf("%d ",cnt2);for(int k=0;k<ans2.size();k++)printf("%d ",ans2[k]);printf("\n");return 0;
}

USACO4.3.3 街道赛跑 解题报告相关推荐

  1. Luogu P2752【usaco4.3.3】街道赛跑-Street Race(图论连通性)

    来源: JZOJ #310,Luogu P2752 题目描述 下图表示一次街道赛跑的跑道.可以看出有一些路口(用 0 到 N 的整数标号),和连接这些路口的箭头.路口 0 是跑道的起点,路口 N是跑道 ...

  2. 【网易2017春招】赶去公司 解题报告

    [网易2017春招]赶去公司 解题报告 标签(空格分隔): 牛客网 题目地址:https://www.nowcoder.com/questionTerminal/5c7657015d3d49369c4 ...

  3. SHU 第十届程序设计联赛(夏季赛) 解题报告

    Problem A: 一日三餐开销 水题,基本上都过了,直接贴代码: 1 #include <iostream> 2 #include <cstdio> 3 using nam ...

  4. [国家集训队2011]拆迁队nbsp;解题报告

    题目: http://cogs.pro/cogs/problem/problem.php?pid=1859 lanxisi带领着他的拆迁队来整治一个街道.这个街道由N个旧房子组成,从左到右编号为1.. ...

  5. uscao 线段树成段更新操作及Lazy思想(POJ3468解题报告)

    线段树成段更新操作及Lazy思想(POJ3468解题报告) 标签: treequerybuildn2cstruct 2011-11-03 20:37 5756人阅读 评论(0) 收藏 举报  分类: ...

  6. 解题报告(十八)数论题目泛做(Codeforces 难度:2000 ~ 3000 + )

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 繁凡出品的全新系列:解题报告系列 -- 超高质量算法题单,配套我写的超高质量的题解和代码,题目难度不一 ...

  7. 【解题报告系列】超高质量题单 + 题解(ACM / OI)超高质量题解

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 繁凡出品的全新系列:解题报告系列 -- 超高质量算法题单,配套我新写的超高质量的题解和代码,题目难度不 ...

  8. 解题报告(三)多项式求值与插值(拉格朗日插值)(ACM / OI)

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 繁凡出品的全新系列:解题报告系列 -- 超高质量算法题单,配套我写的超高质量的题解和代码,题目难度不一 ...

  9. 解题报告(十三)中国剩余定理(ACM / OI)

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 繁凡出品的全新系列:解题报告系列 -- 超高质量算法题单,配套我写的超高质量的题解和代码,题目难度不一 ...

最新文章

  1. 「模型解读」resnet中的残差连接,你确定真的看懂了?
  2. java代码审查规范
  3. PHP:第三章——PHP中控制函数的函数
  4. 常用的后端性能优化六种方式:缓存化+服务化+异步化等
  5. C++模板函数只声明一种类型但输入两种类型参数
  6. 解决问题:Couldn't open file: data/coco.names
  7. C语言实例 区分旅客国籍
  8. 用Swift完成不同View Controller之间的切换
  9. 6. PHP bcompiler
  10. kindle阅读mobi电子书资料共享
  11. PHP编写Android初步
  12. python批量删除行_用python批量删除sheet
  13. 如何让计算机虚拟出多个桌面,多屏显示算什么?win10自带神技能,桌面秒变多屏幕,创建无上限...
  14. 6.20thingworx之bug记录
  15. java 切换系统输入法_系统语言改变时,输入法变成默认输入法分析
  16. 加速更新DNS解析记录的方法
  17. gps测试软件怎么算正常,完整的GPS测试和经济实用的解决方案
  18. python接收http请求_python通过get,post方式发送http请求和接收http响应
  19. 康佳android 9tv,安卓4.4抢先体验:康佳易TV最大规模系统升级
  20. 常见的计算机辅助决策系统有,机器学习辅助决策系统

热门文章

  1. c语言的零碎小知识~
  2. python批处理_python写批处理
  3. 数据库之数据表、约束、事务等操作
  4. java多线程银行取钱_用java线程同步实现银行取款和存款。
  5. Stata如何快速安装外部命令
  6. ZZNUOJ_用C语言编写程序实现1539:读数字(附完整源码)
  7. Excel如何将表格快速复制到另一工作簿中
  8. transform的translate属性
  9. 什么牌子的高端游戏本比较好?来说说外星人
  10. 【应用分身】下载支持应用分身的应用(QQ),开启应用分身,返回桌面,会出现所有应用的分身。(Unisoc)