zoukankan      html  css  js  c++  java
  • 以洛谷P2661信息传递为例总结找环的常见的几种方法

    题目链接:https://www.luogu.com.cn/problem/P2661

    法一:并查集

    当两个点x和y之间存在一条边,且他们的祖先都相同时,就会形成一个环,环的大小为dis[x]+dis[y]+1

    #include <bits/stdc++.h>
    #define Pair pair<int,int>
    using namespace std;
    typedef long long ll;
    const int MAXN=2e5+5;
    const int  INF=0x7fffffff;
    int n,min_=INF;
    int f[MAXN],dis[MAXN];
    void init()
    {
        for(int i=1;i<=n;i++)
            f[i]=i;
    }
    int find_(int v)
    {
        if(f[v]!=v)
        {
            int last=f[v];
            f[v]=find_(f[v]);
            dis[v]+=dis[last];
        }
        return f[v];
    }
    void merge_(int x,int y)
    {
        int tx=find_(x),ty=find_(y);
        if(tx!=ty)
        {
            f[tx]=ty;dis[x]=dis[y]+1;
        }
        else
            min_=min(min_,dis[x]+dis[y]+1);
    }
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        cin>>n;
        init();
        for(int i=1;i<=n;i++)
        {
            int x;cin>>x;
            merge_(i,x);
        }
        cout<<min_<<endl;
        return 0;
    }

    法二:拓扑排序找环

    思路:对一个有向图进行拓扑排序可判断该图是否存在环,如果有拓扑序列则无环,反之则有

    #include <bits/stdc++.h>
    #define Pair pair<int,int>
    using namespace std;
    typedef long long ll;
    const int MAXN=2e5+5;
    const int  INF=0x7fffffff;
    int n,min_=INF,head[MAXN],tot,in[MAXN],visit[MAXN];
    struct node
    {
        int to,nxt;
    }e[MAXN<<1];
    void add(int x,int y)
    {
        e[tot].to=y;e[tot].nxt=head[x];head[x]=tot++;
    }
    vector<int>v1;queue<int>q;
    void topusort()
    {
        while(!q.empty())
        {
            int u=q.front();q.pop();
            v1.push_back(u);visit[u]=1;
            for(int i=head[u];~i;i=e[i].nxt)
            {
                int v=e[i].to;in[v]--;
                if(in[v]==0)q.push(v);
            }
        }
    }
    int dfs(int x)
    {
        visit[x]=1;
        for(int i=head[x];~i;i=e[i].nxt)
        {
            int v=e[i].to;
            if(!visit[v])
                return dfs(v)+1;
        }
        return 1;
    }
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        cin>>n;memset(head,-1,sizeof(head));
        for(int i=1;i<=n;i++)
        {
            int x;cin>>x;
            add(i,x);in[x]++;
        }
        for(int i=1;i<=n;i++)
            if(!in[i])q.push(i);
        topusort();
        for(int i=1;i<=n;i++)
        {
            if(!visit[i])min_=min(dfs(i),min_);
        }
        cout<<min_<<endl;
        return 0;
    }
  • 相关阅读:
    查看 lib 库信息
    评委打分(C++ 容器综合练习)
    二阶段12.16
    对搜狗输入法的使用心得
    二阶段12.14
    二阶段12.13
    二阶段12.12
    典型用户描述
    水王(课堂练习)
    一阶段11.21
  • 原文地址:https://www.cnblogs.com/ljxdtc666/p/12722372.html
Copyright © 2011-2022 走看看