• poj1236 Network of Schools(tarjan缩点)


    题目链接:http://poj.org/problem?id=1236

    题意:有n个学校,学校之间的网络由单向边连接,现在有一个软件要传向每个学校,(单向连通的可以直接传达)

    问最少要传给多少个学校可以全部传达?

    再至少添加几条单向边,可以随便发送给一个学校使全部学校传达到。

    思路:

    先找到连通分量,每个连通分量入度为0的就是要传达的,第一问就是入度为0的个数


    第二问就是添加几条边可以得到使整个图变成一个强连通分量,答案就是连通分量入度为0的个数和出度为0的个数中最大的那个值
    原因:我们将缩完点之后的图看成一个个子树,要想把它们变成一个连通分量就要将出度为0和入度为0的点连起来。
    所以只要只要找两者最大的就行。

    为什么缩点后再计算出度入度呢?

    因为不缩点的话,可能有环,以一个一个点为单位用出度是算不出答案来,只有以一个一个连通分量为单位,计算出度入度。

    代码:

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #define inf 0x3f3f3f3f
    using namespace std;
    typedef long long ll;
    const int maxn=105;
    struct node{
        int to,next;
    }edge[maxn*maxn];
    
    int head[maxn],low[maxn],dfn[maxn],st[maxn];//st模拟栈 
    int in[maxn],out[maxn],visit[maxn],belong[maxn];//belong每个点属于哪个连通分量 
    int n,num,cnt,tot,top,ans1,ans2;
    
    void init()//初始化 
    {
        memset(head,-1,sizeof(head));
        memset(visit,0,sizeof(visit));
        memset(dfn,0,sizeof(dfn));
        memset(low,0,sizeof(low));
        memset(in,0,sizeof(in));
        memset(out,0,sizeof(out));
        memset(st,0,sizeof(st));
        memset(belong,0,sizeof(belong));
        ans1=ans2=cnt=tot=num=top=0;
    }
    
    void add(int u,int v)//前向星加边 
    {
        edge[cnt].to=v;
        edge[cnt].next=head[u];
        head[u]=cnt++;
    }
    
    void tarjan(int u)//tarjan缩点 
    {
        dfn[u]=low[u]=++tot;//赋初值 
        visit[u]=1;//标记进栈 
        st[++top]=u;//进栈 
        for(int i=head[u];i!=-1;i=edge[i].next)//搜索相连的边 
        {
            int v=edge[i].to;
            if(!dfn[v])//没有被搜索过 
            {
                tarjan(v);//搜索 
                low[u]=min(low[u],low[v]);    
            }
            else if(visit[v])//搜索过,已经在栈里 
                low[u]=min(low[u],dfn[v]);
        }
        if(dfn[u]==low[u])//一个连通分量 
        {
            int t;
            num++;//联通分量的编号 
            do{
                t=st[top--];//出栈 
                visit[t]=0;//取消标记 
                belong[t]=num;//记录所在连通分量 
            }while(t!=u);
        }
    }
    
    void solve()
    {
        for(int i=1;i<=n;i++)
            if(!dfn[i])
                tarjan(i);
        for(int i=1;i<=n;i++)
        {
            for(int j=head[i];j!=-1;j=edge[j].next)
            {
                int v=edge[j].to;
                if(belong[i]!=belong[v])//不是同一个缩点 
                {
                    out[belong[i]]++;
                    in[belong[v]]++;
                }
            }
        }
        for(int i=1;i<=num;i++)
        {
            if(!in[i])
                ans1++;
            if(!out[i])
                ans2++;
        }
    }
    
    int main()
    {
        while(scanf("%d",&n)!=EOF)
        {
            init();
            int x;
            for(int i=1;i<=n;i++)
            {
                while(scanf("%d",&x) && x!=0)
                    add(i,x);        
            }
            solve();
            ans2=max(ans1,ans2);
            if(num==1)
                printf("1
    0
    ");
            else
                printf("%d
    %d
    ",ans1,ans2);
        }
        return 0;
    }
  • 相关阅读:
    Analysis Services features supported by SQL Server editions
    Azure DevOps to Azure AppServices
    Power BI For Competition
    Win10开机“提示语音”以及”随机播放音乐”
    Azure DevOps
    Allow Only Ajax Requests For An Action In ASP.NET Core
    Mobile CI/CD 101
    Configure SSL for SharePoint 2013
    AWS Step Function Serverless Applications
    Cordova Upload Images using File Transfer Plugin and .Net core WebAPI
  • 原文地址:https://www.cnblogs.com/xiongtao/p/9998195.html
Copyright © 2020-2023  润新知