zoukankan      html  css  js  c++  java
  • hdu2767强连通加缩点

    https://vjudge.net/contest/156688#problem/B

    题目说了一大堆,前面的没有用,就是让你判断要加几条边才能强连通,用到缩点的知识

    二重循环,判断邻接表下一个点是不是在强连通分量中,入度,出度分别保存下来,输出较大的那一个

    #include<map>
    #include<set>
    #include<list>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<vector>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define pi acos(-1)
    #define ll long long
    #define mod 1000000007
    
    using namespace std;
    
    const int N=20005,maxn=100005,inf=0x3f3f3f3f;
    
    int n,m;//判断是不是在栈中,2为在栈中,1为已访问不在栈中,0为不在栈中
    stack<int>s;
    vector<int>v[N],ans[N];
    int dfn[N],low[N];
    int inans[N],ins[N];
    int num,index;
    int in[N],out[N];
    
    void tarjan(int u)
    {
        ins[u]=2;
        dfn[u]=low[u]=++index;
        s.push(u);
        for(int i=0;i<v[u].size();i++)
        {
            int x=v[u][i];
            if(dfn[x]==0)
            {
                tarjan(x);
                low[u]=min(low[u],low[x]);
            }
            else if(ins[x]==2)low[u]=min(low[u],dfn[x]);
        }
        if(dfn[u]==low[u])
        {
            ++num;
            while(!s.empty()){
                int k=s.top();
                s.pop();
                ins[k]=1;
                inans[k]=num;
                if(k==u)break;
            }
        }
    }
    int main()
    {
        int t;
        cin>>t;
        while(t--){
            index=num=0;
            memset(dfn,0,sizeof(dfn));
            memset(low,0,sizeof(low));
            memset(ins,0,sizeof(ins));
            memset(in,0,sizeof(in));
            memset(out,0,sizeof(out));
            for(int i=1;i<=n;i++)
            {
                v[i].clear();
                ans[i].clear();
            }
            while(!s.empty())s.pop();
            cin>>n>>m;
            while(m--){
                int a,b;
                cin>>a>>b;
                v[a].push_back(b);
            }
            for(int i=1;i<=n;i++)
                if(!dfn[i])
                   tarjan(i);
            if(num==1)
            {
                cout<<0<<endl;
                continue;
            }
            for(int i=1;i<=n;i++)
            {
                for(int j=0;j<v[i].size();j++)
                {
                    int p=v[i][j];
                    if(inans[i]==inans[p])continue;
                    in[inans[i]]=out[inans[p]]=1;
                }
            }
            int a=0,b=0;
            for(int i=1;i<=num;i++)
            {
                if(!in[i])a++;
                if(!out[i])b++;
            }
            cout<<max(a,b)<<endl;
        }
        return 0;
    }
  • 相关阅读:
    全栈程工程师
    月薪8000的程序员和月薪2万的程序员差别在哪里?
    原型中的访问
    关于 基本类型和复合类型 用== 判断的小问题
    使用原型解决构造函数问题
    前端工程师学习路线 --书籍
    程序员成长之路
    GIT学习(1) Pull和Fetch
    OO面向对象编程:第四单元总结及课程总结
    OO面向对象编程:第三单元总结
  • 原文地址:https://www.cnblogs.com/acjiumeng/p/6655896.html
Copyright © 2011-2022 走看看