POJ1236-Network of Schools


题解:
问题等价于:
1 1 、至少要选几个点,才能使得从这些点出发能到达所有点。
2、至少要加几条边,才能使得这个图成为一个强连通分量。
Tarjan T a r j a n 缩点后,问题 1 1 的答案即为入度为0的点的个数。
对于问题 2 2 ,需要为所有入度为0的点增加一条入边,为所有出度为 0 0 的点增加一条出边。
假设入度为0的点有 n n 个,出度为0的点有 m m 个,那么答案即为maxnm
注意原图就是一个强连通分量的特殊情况。
Code C o d e :

#include<iostream>
#include<vector>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#define N 10005
using namespace std;
int dfn[N],low[N],deep,a[N],top,flag[N],color[N],sum,cnt[N],out[N],in[N];
vector<int> edge[N];
void tarjan(int u)
{
    low[u]=dfn[u]=++deep;
    a[++top]=u;flag[u]=true;
    for(int i=0;i<edge[u].size();i++)
    {
        int v=edge[u][i];
        if(!dfn[v])
        {
            tarjan(v);
            low[u]=min(low[u],low[v]);
        }else if(flag[v])
            low[u]=min(low[u],low[v]);
    }
    if(low[u]==dfn[u])
    {
        color[u]=++sum;
        flag[u]=0;
        while(a[top]!=u)
        {
            flag[a[top]]=false;
            color[a[top--]]=sum;
        }
        top--;
    }
}
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        int x;
        scanf("%d",&x);
        while(x)
        {
            edge[i].push_back(x);
            scanf("%d",&x);
        }
    }
    memset(dfn,0,sizeof(dfn));
    memset(flag,false,sizeof(flag));
    for(int i=1;i<=n;i++)
        if(!dfn[i])tarjan(i);
    for(int u=1;u<=n;u++)
    {
        for(int i=0;i<edge[u].size();i++)
        {
            int v=edge[u][i];
            if(color[u]!=color[v])
            {
                in[color[v]]++;
                out[color[u]]++;
            }
        }
        cnt[color[u]]++;
    }
    int tot=0,ans=0;
    for(int i=1;i<=sum;i++)
        if(in[i]==0)tot++;else 
            if(out[i]==0)ans++;
    if(sum==1)
    {
        puts("1");
        puts("0");
    }else
    {
        printf("%d\n",tot);
        printf("%d\n",max(ans,tot));
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JackflyDC

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值