zoukankan      html  css  js  c++  java
  • POJ1236

    题意

    要求我们输出:

    1、至少给几个点传递消息,才能保证所有消息传遍整个图;

    2、至少添加几条边,才能使任意选择一个点,消息都能传遍整个图。

    思路

    强连通模板题。

    第一问:强连通分量缩点之后有几个入度为0的点。

    第二问:首先我们画个图,就能发现只要把入度为0的点直接连一条边到入度为0的点上,就可以形成一个环,所以答案是:max(入度为0的点,出度为0的点)。

    3、注意一下特判,如果SCC只有一个,输出0即可。

    AC代码

    #include<stdio.h>
    #include<iostream>
    #include<queue>
    #include<string.h>
    using namespace std;
    #define inf 0x3f3f3f3f
    typedef long long ll;
    const int N=110;
    
    int n,m,tot,num,countt,top,head[10*N];
    int in[N],out[N],low[N],dfn[N],co[N],st[N],si[N];
    bool book[N][N];
    
    struct node
    {
        int nextt,v;
    } e[N*N*10];
    
    void add(int u,int v)
    {
        tot++;
        e[tot].nextt=head[u];
        head[u]=tot;
        e[tot].v=v;
    }
    
    void tarjan(int u)
    {
        //top=0;
        dfn[u]=low[u]=++num;
        st[++top]=u;//入栈
        for(int i=head[u]; i!=-1; i=e[i].nextt)
        {
            int v=e[i].v;
            if(dfn[v]==0)
            {
                tarjan(v);
                low[u]=min(low[u],low[v]);
            }
            else if(co[v]==0)
                low[u]=min(low[u],dfn[v]);
        }
        if(low[u]==dfn[u])
        {
            co[u]=++countt;//countt是连通分量个数
            ++si[countt];
            while(st[top]!=u)
            {
                ++si[countt];
                co[st[top--]]=countt;
            }
            --top;//出栈
        }
    }
    
    void init()
    {
        countt=num=top=0,tot=-1;
        memset(head,-1,sizeof(head));
        memset(dfn,0,sizeof(dfn));
        memset(co,0,sizeof(co));
        memset(in,0,sizeof(in));
        memset(out,0,sizeof(out));
        memset(book,0,sizeof(book));
    }
    
    int main()
    {
        while(~scanf("%d",&n))
        {
            init();
            for(int i=1; i<=n; i++)
            {
                while(1)
                {
                    int x;
                    scanf("%d",&x);
                    if(x==0)
                        break;
                    add(i,x);
                    book[i][x]=1;
                }
            }
            for(int i=1; i<=n; i++)
            {
                if(dfn[i]==0)
                    tarjan(i);
            }
            for(int i=1; i<=n; i++)
            {
                for(int j=1; j<=n; j++)
                {
                    if(book[i][j]&&(co[i]!=co[j]))//说明点i可以到j&&i和j不在同一个连通分量里面
                    {
                        out[co[i]]++;
                        in[co[j]]++;
                    }
                }
            }
            int inn=0,outt=0;
            for(int i=1; i<=countt; i++)
            {
                if(out[i]==0)
                    outt++;
                if(in[i]==0)
                    inn++;
            }
            if(countt==1)//特判
            {
                printf("1
    ");
                printf("0
    ");
            }
            else
            {
                //至少给几个点传递消息,才能保证所有消息传遍整个图
                printf("%d
    ",inn);//输出入度为0的个数
    
                //至少添加几条边,才能使任意选择一个点,消息都能传遍整个图
                int ans=max(outt,inn);//输出入度为0和出度为0的max
                printf("%d
    ",ans);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    很牛逼的android真机调试,手机、平板、电视都可
    设置TextView文字居中
    设置文本编辑器的按回车时触发的事件
    windows搭建virtualbox虚拟机安装的android环境
    Android EditText不弹出输入法焦点问题的总结
    MAVEN 的常用命令
    PuTTY_0.67.0.0工具链接linux
    CentOS6.8安装
    互亿无线短信验证码
    MYSQL: sql中某一个字段内容为用逗号分割的字符串转换成多条数据
  • 原文地址:https://www.cnblogs.com/OFSHK/p/13714781.html
Copyright © 2011-2022 走看看