zoukankan      html  css  js  c++  java
  • POJ2762 Going from u to v or from v to u? 强连通+缩点

    题目链接:

    poj2762




    题意:

    给出一幅单向图。问这张图是否满足   随意两点ab 都能 从a到达b 或  从b到达a





    题解思路:

    推断一幅图是否满足弱连通

    首先想到的是将图中的 强连通分量(能互相到达的顶点集)  进行缩点

    然后再依据原有边 又一次建图

    假设缩点后的图是一条单链(回路,通路都能够)   则一定满足弱连通


    推断是否是一条单链 能够依据建图过程中得到 入度 出度 数组进行推断

    某点的入度 或 出度假设大于1则一定不是单链

    另外单链仅仅能有一条  不能有多个点入度=0



    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<queue>
    #define maxn 1050
    using namespace std;
    struct node
    {
        int to,next;
    } edge[maxn*6];
    int head[maxn];
    int s;
    
    int dfn[maxn],low[maxn],num;
    
    int sta[maxn],insta[maxn],top;
    
    int belong[maxn],block;
    
    void init()
    {
        memset(head,-1,sizeof(head));
        memset(insta,0,sizeof(insta));
        memset(dfn,0,sizeof(dfn));
        block=s=num=top=0;
    }
    
    void addedge(int a,int b)
    {
        edge[s]= {b,head[a]};
        head[a]=s++;
    }
    
    void Tarjan(int u,int pre)
    {
        dfn[u]=low[u]=++num;
        insta[u]=1;
        sta[top++]=u;
        for(int i=head[u]; i!=-1; i=edge[i].next)
        {
            int v=edge[i].to;
            if(!dfn[v])
            {
                Tarjan(v,u);
                low[u]=min(low[u],low[v]);
            }
            else if(insta[v])                    //回边
                low[u]=min(low[u],dfn[v]);
        }
        if(dfn[u]==low[u])                      //缩点
        {
            int d;
            block++;
            while(d!=u)
            {
                d=sta[--top];
                insta[d]=0;
                belong[d]=block;
            }
        }
    }
    
    int rebuild(int n)
    {
        int indegree[maxn]= {0};
        int outdegree[maxn]={0};
        int u,v;
        for(int i=1; i<=n; i++)                            //又一次建图
        {
            u=belong[i];
            for(int j=head[i]; j!=-1; j=edge[j].next)
            {
                v=edge[j].to;
                v=belong[v];
                if(u!=v)          //不在同一个强连通分量才干建边
                {
                    outdegree[u]++;
                    indegree[v]++;
                    if(indegree[v]>1||outdegree[u]>1)
                        return 0;
                }
            }
        }
        int ss=0;
        for(int i=1; i<=block; i++)
            if(!indegree[i])
                ss++;
        if(ss>1)             //入度=0的点有多个
            return 0;
        return 1;
    }
    
    int main()
    {
        int n,m,a,b;
        int T;
        scanf("%d",&T);
        while(T--)
        {
            init();
            scanf("%d%d",&n,&m);
            while(m--)
            {
                scanf("%d%d",&a,&b);
                addedge(a,b);
            }
            for(int i=1;i<=n;i++)   //
                if(!dfn[i])         //有向图Tarjan算法
                    Tarjan(i,-1);   //
    
            if(rebuild_topsort(n))
                cout<<"Yes"<<endl;
            else
                cout<<"No"<<endl;
        }
        return 0;
    }
    




  • 相关阅读:
    教程:在 Visual Studio 中开始使用 Flask Web 框架
    教程:Visual Studio 中的 Django Web 框架入门
    vs2017下发现解决python运行出现‘No module named "XXX""的解决办法
    《sqlite权威指南》读书笔记 (一)
    SQL Server手工插入标识列
    hdu 3729 I'm Telling the Truth 二分图匹配
    HDU 3065 AC自动机 裸题
    hdu 3720 Arranging Your Team 枚举
    virtualbox 虚拟3台虚拟机搭建hadoop集群
    sqlserver 数据行统计,秒查语句
  • 原文地址:https://www.cnblogs.com/mfmdaoyou/p/6688760.html
Copyright © 2011-2022 走看看