蓝桥杯_历届试题 发现环

问题描述
  小明的实验室有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

还有两天就国赛了,今天做了一下去年的题,第一个编程题在以前做过一下的前提下还是错了三次才对的,国赛真的要凉啊,看来,这两天还是统统整理一下搜索的题比较实在........

第一次错误是因为开始以为边是有向边呢,10分,第二次改成双向边做,当时也是已经考虑到了如果由当前节点返回到父亲节点不应该被考虑为一个环,但是没有想到怎么改,还是错了,20分,第三次想到了怎么判断由当前节点指向,但是细节还是有错误,比如:枚举当前节点p的路径,不能由p节点返回到他的父亲节点,但是考虑成了儿子节点不能返回p节点了,然后又错了,20分

然后就是最终正确的做法了:我们这里将有向图换成无向图,首先应该图的大小就会扩大两倍,注意数组的大小,然后唯一一点和无向图不同的就是要特殊判断当前节点不能返回他的父亲节点,如果这样的话就会是两个节点的环,没有任何意义,那么我们继续向后遍历的时候只要遍历到任何一个已经被访问过的点,那么就证明我们已经发现了这个环,只要不断地沿着这个环向上遍历,就可以得到环上的任意一个点!

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#define INF 0x3f3f3f3f
#define ll long long
using namespace std;
const int MAXN = 210000;
struct Edge
{
    int v,next;
}edge[MAXN];
int head[MAXN],per[MAXN],k,vis[MAXN],len,ans[MAXN];
void Add_edge(int x,int y)
{
    edge[k].v = y;edge[k].next = head[x];head[x] = k++;
}
bool falg = false;
void dfs(int p,int f)
{
    for(int i = head[p];i != -1;i = edge[i].next)
    {
        if(falg) return ;
        int v = edge[i].v;
        if(v == f) continue;
        per[v] = p;
        if(vis[v])
        {
            ans[len++] = p;
            while(per[p] != v)
            {
                ans[len++] = per[p];
                p = per[p];
            }
            ans[len++] = v;
            falg = true;
            return ;
        }
        vis[v] = 1;
        dfs(v,p);
    }
    return ;
}
int main()
{
    int n;
    scanf("%d",&n);
    int x,y;k = 0;len = 0;
    for(int i = 1;i <= n;i ++) per[i] = i;
    memset(head,-1,sizeof(head));
    for(int i = 0;i < n;i ++)
    {
        scanf("%d%d",&x,&y);
        Add_edge(x,y);
        Add_edge(y,x);
    }
    memset(vis,false,sizeof(vis));
    vis[1] = 1;
    dfs(1,0);
    sort(ans,ans+len);
    for(int i = 0;i < len;i ++)
        printf("%d%c",ans[i],i==len-1?'\n':' ');
}

猜你喜欢

转载自blog.csdn.net/li1615882553/article/details/80443275