Pku1236 Network of Schools

n个学校构成一个有向图,通过m条边连接,一:问至少向图中多少个学校投放软件,可以使得所有学校直接或者间接的通过边(假设存在边(u,v),则向u投放v可以得到,而向v投放u不能通过v直接得到)得到软件(假设每次投放的软件无穷多)。二:问至少添加多少条有向边,可以使得只用向任意一个学校投放软件后,别的学校都能得到软件
输入
第一行给出数字N,N<=100
接下来N行给出每个点的连通情况,每行给出一些数字代表第i个学校与哪些学校相连接,每行输入以0代表结束
输出
如题

Sample Input
5
2 4 3 0
4 5 0
0
0
1 0
Sample Output
1
2

其实就是强连通缩点,
问一是统计缩点后有多少分量入度为0,
问二是指至少添加多少边使得图强连通。
然后统计入度为0的点的个数in和出度为0的点的个数ou,
则问一输出in,问二如果整个图强连通则输出0,否则输出max{in,ou}。
为什么是max{in,ou}?
因为要使得图强连通,则必定每个点的出度以及入度都不为0

#include<algorithm>
#include<cstdio>
using namespace std;
int son[10100],n,m,ans1,group,low[10100],dfn[10100],st[10100],tot,now[10100],used[11000],popp[11000],topp[11000],a[11000],b[11000],ans2;
void add(int x,int y)
{
    tot++;
    now[tot]=son[x];
    son[x]=tot;
}
int top,sum,cnt,totle;
void dfs(int deep)
{
    st[++top]=deep;
    dfn[deep]=++cnt;
    low[deep]=dfn[deep];
    int nnow=top;
    for(int i=son[deep];i;i=now[i])
        if(!used[b[i]])
        {
            if(!dfn[b[i]])
                dfs(b[i]);
            low[deep]=min(low[b[i]],low[deep]);
        }
    if(dfn[deep]==low[deep])
    {
        totle++;
        for(int i=nnow;i<=top;i++)
            used[st[i]]=totle;
        top=nnow-1;
    }
}
int main()
{
    int v,k=0;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&v);
        while(v)
        {
            add(i,v);
            a[++k]=i;
			b[k]=v;
            scanf("%d",&v);
        }
    }
    for(int i=1;i<=n;i++)
        if(!used[i])dfs(i);
    for(int i=1;i<=k;i++)
        if(used[a[i]]!=used[b[i]])
		   ++popp[used[a[i]]],
		   topp[used[b[i]]]++;
    for(int i=1;i<=totle;i++)
    {
        if(topp[i]==0)
		   ans1++;
        if(popp[i]==0)
		   ans2++;
    }
    ans2=max(ans1,ans2);
    if(totle==1)
	   ans2=0;
    printf("%d
%d",ans1,ans2);
}

  

#include<cstdio>
#include<algorithm>
using namespace std;
int s[10010],st[110],hea[110],en[110],in[110],dfn[110],low[110],cd[110],rd[110],num,cnt,top,n,m;
void tarjan(int x)
{
    low[x]=dfn[x]=++num;
    st[++top]=x;
    for(int i=hea[x];i<en[x];i++)
    {
        int y=s[i];
        if(!dfn[y])
        {
            tarjan(y);
            low[x]=min(low[x],low[y]);
        }
        else if(!in[y])
            low[x]=min(low[x],dfn[y]);
    }
    if(low[x]==dfn[x])
    {
        cnt++;
        while(top&&st[top]!=x)in[st[top--]]=cnt;
        in[st[top--]]=cnt;
    }
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        en[i]=hea[i]=en[i-1];
        while(scanf("%d",s+en[i])&&s[en[i]])en[i]++;
    }
    for(int i=1;i<=n;i++)
        if(!dfn[i])
            tarjan(i);
    for(int i=1;i<=n;i++)
        for(int j=hea[i];j<en[i];j++)
            if(in[i]!=in[s[j]])
                cd[in[i]]++,rd[in[s[j]]]++;
    int c=0,r=0;
    for(int i=1;i<=cnt;i++)
    {
        if(!cd[i])c++;
        if(!rd[i])r++;
    }
    printf("%d
",r);
    if(cnt==1)puts("0");
    else printf("%d
",max(c,r));
    return 0;
}