题目链接:http://lx.lanqiao.cn/problem.page?gpid=T453

问题描述

  小明的实验室有N台电脑,编号1~N。原本这N台电脑之间有N-1条数据链接相连,恰好构成一个树形网络。在树形网络上,任意两台电脑之间有唯一的路径相连。

  不过在最近一次维护网络时,管理员误操作使得某两台电脑之间增加了一条数据链接,于是网络中出现了环路。环路上的电脑由于两两之间不再是只有一条路径,使得这些电脑上的数据传输出现了BUG。

  为了恢复正常传输。小明需要找到所有在环路上的电脑,你能帮助他吗?

输入格式
  第一行包含一个整数N。
  以下N行每行两个整数a和b,表示a和b之间有一条数据链接相连。

  对于30%的数据,1 <= N <= 1000
  对于100%的数据, 1 <= N <= 100000, 1 <= a, b <= N

  输入保证合法。

输出格式
  按从小到大的顺序输出在环路上的电脑的编号,中间由一个空格分隔。
样例输入
5
1 2
3 1
2 4
2 5
5 3
样例输出
1 2 3 5
 
解题思路:第一种解法是用拓扑排序的方式,把度数为1的点去掉,然后剩下的度数为2的点就是答案了,第二种解法是用并查集找到环上相邻的两个点,然后用dfs一个为起点一个为终点,就可以搜索出答案。
代码:
第一种解法:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=;
int n,tot,head[maxn],in[maxn];
vector<int> ans;
struct node{
int to,next;
}edge[*maxn];
void add(int u,int v){
edge[tot].to=v;
edge[tot].next=head[u];
head[u]=tot++;
}
void topsort(){
queue<int> que;
for(int i=;i<=n;i++){
if(in[i]==)que.push(i);
}
while(que.size()){
int now=que.front();
que.pop();
for(int i=head[now];i!=-;i=edge[i].next){
int v=edge[i].to;
in[v]--;
if(in[v]==)que.push(v);
}
}
for(int i=;i<=n;i++){
if(in[i]==)ans.push_back(i);
}
}
int main(){
cin>>n;
for(int i=;i<=n;i++)head[i]=-;
for(int i=;i<n;i++){
int u,v;
cin>>u>>v;
add(u,v);
add(v,u);
in[u]++; in[v]++;
}
topsort();
sort(ans.begin(),ans.end());
for(int i=;i<ans.size();i++)
{
printf("%d",ans[i]);
if(i!=ans.size()-)cout<<" ";
else cout<<endl;
}
return ;
}

第二种解法:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=;
int n,tot,st,ed,head[maxn],par[maxn],pre[maxn],vis[maxn];
vector<int> ans;
struct node{
int to,next;
}edge[*maxn];
void add(int u,int v){
edge[tot].to=v;
edge[tot].next=head[u];
head[u]=tot++;
}
int find(int x){
if(x==par[x])return x;
else return par[x]=find(par[x]);
}
void unite(int x,int y){
int fx=find(x),fy=find(y);
par[fx]=fy;
}
void dfs(int x){
vis[x]=;
for(int i=head[x];i!=-;i=edge[i].next){
int v=edge[i].to;
if(!vis[v]){
if(x==st&&v==ed)continue;
vis[v]=;
pre[v]=x;
if(v==ed)return;
dfs(v);
}
}
}
int main(){
cin>>n;
for(int i=;i<=n;i++){
head[i]=-;
par[i]=i;
}
for(int i=;i<n;i++){
int u,v;
cin>>u>>v;
add(u,v);
add(v,u);
if(find(u)!=find(v))unite(u,v);
else{
st=u;
ed=v;
}
}
pre[st]=st;
dfs(st);
int tmp=ed;
ans.push_back(ed);
while(pre[tmp]!=tmp){
tmp=pre[tmp];
ans.push_back(tmp);
}
sort(ans.begin(),ans.end());
for(int i=;i<ans.size();i++)
{
printf("%d",ans[i]);
if(i!=ans.size()-)cout<<" ";
else cout<<endl;
}
return ;
}

发现环 (拓扑或dfs)的更多相关文章

  1. 蓝桥杯 试题 历届试题 发现环 并查集+dfs

    问题描述 小明的实验室有N台电脑,编号1~N.原本这N台电脑之间有N-1条数据链接相连,恰好构成一个树形网络.在树形网络上,任意两台电脑之间有唯一的路径相连. 不过在最近一次维护网络时,管理员误操作使 ...

  2. 拓扑排序详解(梅开二度之dfs版按字典序输出拓扑路径+dfs版输出全部拓扑路径

    什么是拓扑排序? 先穿袜子再穿鞋,先当孙子再当爷.这就是拓扑排序! 拓扑排序说白了其实不太算是一种排序算法,但又像是一种排序(我是不是说了个废话qwq) 他其实是一个有向无环图(DAG, Direct ...

  3. ACM/ICPC 之 拓扑排序+DFS(POJ1128(ZOJ1083)-POJ1270)

    两道经典的同类型拓扑排序+DFS问题,第二题较第一题简单,其中的难点在于字典序输出+建立单向无环图,另外理解题意是最难的难点,没有之一... POJ1128(ZOJ1083)-Frame Stacki ...

  4. 拓扑排序-DFS

    拓扑排序的DFS算法 输入:一个有向图 输出:顶点的拓扑序列 具体流程: (1) 调用DFS算法计算每一个顶点v的遍历完成时间f[v] (2) 当一个顶点完成遍历时,将该顶点放到一个链表的最前面 (3 ...

  5. 发现环——第八届蓝桥杯C语言B组(国赛)第四题

    原创 标题:发现环 小明的实验室有N台电脑,编号1~N.原本这N台电脑之间有N-1条数据链接相连,恰好构成一个树形网络.在树形网络上,任意两台 电脑之间有唯一的路径相连. 不过在最近一次维护网络时,管 ...

  6. 2017第八届蓝桥杯决赛(C++ B组)4.发现环

    描述 小明的实验室有N台电脑,编号1~N.原本这N台电脑之间有N-1条数据链接相连,恰好构成一个树形网络.在树形网络上,任意两台电脑之间有唯一的路径相连. 不过在最近一次维护网络时,管理员误操作使得某 ...

  7. HDU 3342 Legal or Not(有向图判环 拓扑排序)

    Legal or Not Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tota ...

  8. 拓扑排序+DFS(POJ1270)

    [日后练手](非解题) 拓扑排序+DFS(POJ1270) #include<stdio.h> #include<iostream> #include<cstdio> ...

  9. 第八届蓝桥杯C/C++程序设计本科B组决赛 ——发现环(编程大题_签到题_tarjan判环)

    标题:发现环 小明的实验室有N台电脑,编号1~N.原本这N台电脑之间有N-1条数据链接相连,恰好构成一个树形网络.在树形网络上,任意两台电脑之间有唯一的路径相连. 不过在最近一次维护网络时,管理员误操 ...

随机推荐

  1. C#设计模式之4:装饰者模式

    装饰者模式 背景是有一家星巴兹咖啡店,由于客源充足,所以决定重新设计他们的收费系统,以前的收费系统中只定义了一个表示饮料的Beverage的基类,它里面定义了一个Cost的方法用来计算饮料的花费,但是 ...

  2. CentOS7 下面安装jdk1.8

    1. 卸载已有的jdk rpm -qa |grep jdk |xargs rpm -e --nodeps 2. 使用xftp上传 jdk 的文件我这里上传的是 jdk-8u121-linux-x64. ...

  3. [转帖] 百度知道: KMS 和OSPP

    https://zhidao.baidu.com/question/1819332749671662308.html Key Management Service (KMS).目前Windows Se ...

  4. SQLSERVER sa 用户密码修改的方法

    本次驱动人生病毒的收获 . 偷懒总会有报应. . 应用(数据库或者是web应用nginx等.)都不要使用最高级别权限用户来使用 虽然这样的环境问题最少. . 密码还是需要定期更换的,虽然有成本,但是也 ...

  5. ORA-12541:TNS:无监听程序 解决办法

    昨天我在一台win7笔记本中安装了oracle11g,然后打算用另一个win10的笔记本使用plsql developer局域网内连接访问oracle数据库.但是遇到ORA-12541:TNS:无监听 ...

  6. day 7-16 单表查询

    一.准备工作 先把表建立好,方便一会查询. create table emp( id int not null unique auto_increment, name varchar(20) not ...

  7. LODOP打印控件进行批量打印

    Lodop打印控件批量打印的方式:1.批量打印每页内容相同的:(1)批量打印相同内容的很多纸张,可以设置打印份数,把该内容打印出多份.2.批量打印每页不同内容的:(1)通过在一个任务中分页,循环添加页 ...

  8. CSS3之box-sizing属性

    box-sizing本身有三个属性:content-box(默认).border-box和padding-box. content-box:border与padding均不算入width中: bord ...

  9. 【python练习题】程序17

    #题目:输入一行字符,分别统计出其中英文字母.空格.数字和其它字符的个数. s = input('请输入字符串:') alf = 0 space = 0 digi = 0 other = 0 for ...

  10. How to write to an event log by using Visual C#

    using System; using System.Diagnostics; namespace WriteToAnEventLog_csharp { /// Summary description ...