zoukankan      html  css  js  c++  java
  • hdu2767(图的强连通)

    //题意:问需要添加几条边使得这张图成为每个点都等价(强连通图)

    我们先把图中的强连通分量缩点
    可能他本身就是满足条件,那么直接输出0
    经过缩点后,就可以把强连通分量看成一个个独立的点,在这张图上搞一个强连通图,我们可以根据强连通的性质,也就是每个点都要有被指向边和出去的边,那么也就是求一下每个点(强连通分量)的入度和出度,把出度==0的点个数加起来,把入度==0的点个数加起来,比一比谁大,输出谁,因为我们可以直接在入度为0和出度为0的两点间加边,所以取大的那个就满足。

    #include<iostream>
    #include<cstdio>
    #include<math.h>
    #include<queue>
    #include<stdlib.h>
    #include<string>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    typedef long long LL;
    #define PI acos(-1.0)
    #define N 20010
    
    struct asd{
        int to;
        int next;
    };
    asd q[N*3];
    int head[N*3];
    int tol;
    
    int low[N];
    int dfn[N];
    int vis[N];
    int stap[N];
    int in[N];
    int kr[N];
    int kc[N];
    int tp,p;
    int cnt;
    int n;
    
    void tarjan(int u)
    {
        dfn[u]=low[u]=++tp;
        stap[++p]=u;
        vis[u]=1;
        for(int i=head[u];i!=-1;i=q[i].next)
        {
            int k=q[i].to;
            if(!dfn[k])
            {
                tarjan(k);
                low[u]=min(low[u],low[k]);
            }
            else if(vis[k])
            {
                low[u]=min(low[u],dfn[k]);
            }
        }
        if(dfn[u]==low[u])
        {
            cnt++;
            int temp;
            while(1)
            {
                temp=stap[p];
                vis[temp]=0;
                in[temp]=cnt;
                --p;
                if(temp==u)
                    break;
            }
        }
    }
    void soga()
    {
        if(cnt==1)
        {
            printf("0
    ");
            return;
        }
        int pr,pc;
        memset(kr,0,sizeof(kr));
        memset(kc,0,sizeof(kc));
        for(int i=1;i<=n;i++)
        {
            for(int k=head[i];k!=-1;k=q[k].next)
            {
                int v=q[k].to;
                if(in[v]!=in[i])
                {
                    kr[in[v]]++;
                    kc[in[i]]++;
                }
            }
        }
        pc=pr=0;
        for(int i=1;i<=cnt;i++)
        {
            if(!kr[i])
            {
                pr++;
            }
            if(!kc[i])
            {
                pc++;
            }
        }
        printf("%d
    ",max(pr,pc));
    }
    
    
    void add(int a,int b)
    {
        q[tol].to=b;
        q[tol].next=head[a];
        head[a]=tol++;
    }
    
    int main()
    {
        int m;
        int T;
        scanf("%d",&T);
        while(T--)
        {
            int a,b;
            scanf("%d%d",&n,&m);
            tol=0;
            memset(head,-1,sizeof(head));
            for(int i=0;i<m;i++)
            {
                scanf("%d%d",&a,&b);
                add(a,b);
            }
            cnt=p=tp=0;
            memset(dfn,0,sizeof(dfn));
            memset(vis,0,sizeof(vis));
            memset(in,0,sizeof(in));
    
            for(int i=1;i<=n;i++)
            {
                if(!dfn[i])
                    tarjan(i);
            }
            soga();
        }
        return 0;
    }
  • 相关阅读:
    antd Upload的使用
    table 的使用方法
    标题前点的制作
    插件multiBtnList的使用
    render的写法
    数据请求
    实体类为什么使用包装类
    el-table中如何遍历数组中对象里的数组?
    关于hash的描述,hashcode etc
    Java集合框架详解
  • 原文地址:https://www.cnblogs.com/keyboarder-zsq/p/5934542.html
Copyright © 2011-2022 走看看