zoukankan      html  css  js  c++  java
  • tarjan通俗易懂题

    洛谷2661

    https://www.luogu.org/problemnew/show/P2661

    分析:求缩点后成环中,环大小最小的size

    #include<bits/stdc++.h>
    using namespace std;
    const int M=2e5+5;
    vector<int>e[M];
    int vis[M],dfn[M],low[M],cnt,ans=M;
    stack<int>S;
    void tarjan(int u){
        dfn[u]=low[u]=++cnt;
        vis[u]=1;
        S.push(u);
        for(int i=0;i<e[u].size();i++){
            int v=e[u][i];
            if(!dfn[v]){
                tarjan(v);
                low[u]=min(low[u],low[v]);
            }
            else if(vis[v])
                low[u]=min(low[u],dfn[v]);
        }
        if(low[u]==dfn[u]){
            int countt=0;
            while(true){
                int t=S.top();
                S.pop();
                vis[t]=0;
                countt++;
                if(t==u)
                    break;
            }
            if(countt>1)
                ans=min(ans,countt);
        }
    }
    int main(){
    
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            int x;
            scanf("%d",&x);
            e[i].push_back(x);
        }
        for(int i=1;i<=n;i++){
            if(!dfn[i])
                tarjan(i);
        }
        cout<<ans;
        return 0;
    }
    View Code

     https://www.luogu.org/problemnew/show/P1726

    分析:还是求环的大小,不过要在存路径时加些操作

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<stack>
    #include<vector>
    using namespace std;
    const int M=5e4+4;
    int dfn[M],low[M],vis[M],a[M],b[M],cnt;
    vector<int>e[M];
    stack<int>S;
    int ans;
    void tarjan(int u){
        dfn[u]=low[u]=++cnt;
        vis[u]=1;
        S.push(u);
        for(int i=0;i<e[u].size();i++){
            int v=e[u][i];
            if(!dfn[v]){
                tarjan(v);
                low[u]=min(low[u],low[v]);
            }
            else if(vis[v])
                low[u]=min(low[u],dfn[v]);
        }
        if(low[u]==dfn[u]){
            int countt=0;
            while(true){
                int t=S.top();
                S.pop();
                vis[t]=0;
                a[countt++]=t;
                if(t==u)
                    break;
            }
            if(ans<=countt){
                sort(a,a+countt);
                if(ans==countt){
                    int flag=0;
                    for(int i=0;i<countt;i++)
                        if(a[i]<b[i]){
                            flag=1;
                            break;
                        }
                        else if(a[i]>b[i])
                            break;
                    if(flag==1)
                        for(int i=0;i<countt;i++)
                            b[i]=a[i];
                }
                else{
                    for(int i=0;i<countt;i++)
                        b[i]=a[i];
                }
                ans=countt;
            }
        }
    }
    int main(){
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++){
            int u,v,t;
            scanf("%d%d%d",&u,&v,&t);
            if(t==1)
                e[u].push_back(v);
            else
                e[u].push_back(v),e[v].push_back(u);
    
        }
        for(int i=1;i<=n;i++)
            if(!dfn[i])
                tarjan(i);
        printf("%d
    ",ans);
        for(int i=0;i<ans;i++){
            printf("%d ",b[i]);
        }
        return 0;
    }
    View Code

    https://www.luogu.org/problemnew/show/P2341

    分析:所求量一定为经缩点后唯一出度为0的强联通分量的大小

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<stack>
    #include<vector>
    using namespace std;
    const int M=1e4+4;
    const int N=5e4+5;
    vector<int>e[M];
    
    int out[M],in[M],dfn[M],low[M],vis[M],sz[N],cnt,tot,cmp[N];
    stack<int>S;
    void tarjan(int u){
        low[u]=dfn[u]=++cnt;
        vis[u]=1;
        S.push(u);
        for(int i=0;i<e[u].size();i++){
            int v=e[u][i];
            if(!dfn[v]){
                tarjan(v);
                low[u]=min(low[u],low[v]);
            }
            else if(vis[v])
                low[u]=min(low[u],dfn[v]);
        }
        if(dfn[u]==low[u]){
            int countt=0;
            tot++;
            while(true){
                int t=S.top();
                S.pop();
                vis[t]=0;
                cmp[t]=tot;
                countt++;
                if(t==u)
                    break;
            }
            sz[tot]=countt;
        }
    }
    int main(){
        int n,m;
        scanf("%d%d",&n,&m);
        int u,v;
        for(int i=1;i<=m;i++){
    
            scanf("%d%d",&u,&v);
            e[u].push_back(v);
        }
    
        for(int i=1;i<=n;i++)
            if(!dfn[i])
                tarjan(i);
        int sum=0;
        for(int i=1;i<=n;i++)
        for(int j=0;j<e[i].size();j++){
            int v=e[i][j];
            if(cmp[i]!=cmp[v])
                out[cmp[i]]++,in[cmp[v]]++;
        }
        int countt=0,sign;
        for(int i=1;i<=tot;i++)
            if(out[i]==0)
                countt++,sign=i;
        if(countt>1)
            return puts("0"),0;
        printf("%d
    ",sz[sign]);
    
        return 0;
    }
    View Code
  • 相关阅读:
    complicated用法
    Vue安装并创建一个简单项目
    使用PyCharm创建Django项目及基本配置
    [hackerrank]John and GCD list
    在Web应用程序中执行计划任务(多线程)
    随笔,想了个同步的方案。
    文摘.
    csdn sql 搜索相关帖子。
    Url Rewriting,二级域名,重定向
    杂言
  • 原文地址:https://www.cnblogs.com/starve/p/11192740.html
Copyright © 2011-2022 走看看