COGS 908 校园网

/*
Tarjan缩点之后
强联通分量建图 统计每个强联通分量的出入度
第一问就是入度为0的 强联通分量的个数
第二问 为了高效的使每个强联通分量都有出入度
要把出度为零的强联通分量连到入度为零的点上 这样得到的边数是最少的
ans2并不是桥的数目 这样不是最少.....
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 110
#define maxm 10010
using namespace std;
int n,num,g[maxn][maxn],head[maxn],sum,tot,belong[maxn];
int dfn[maxn],low[maxn],stack[maxm],top,f[maxn],ans1,ans2;
int chu[maxn],ru[maxn];
struct node
{
int u,v,pre;
}e[maxm];
struct Node
{
int c[maxn];
int size;
}ans[maxn];
int init()
{
int x=;char s;bool f=;s=getchar();
while(s<''||s>''){if(s=='-')f=;s=getchar();}
while(s>=''&&s<=''){x=x*+s-'';s=getchar();}
if(f)return -x;return x;
}
void Add(int from,int to)
{
num++;
e[num].u=from;
e[num].v=to;
e[num].pre=head[from];
head[from]=num;
}
void Tarjan(int s)
{
dfn[s]=low[s]=++tot;
stack[++top]=s;
f[s]=;
for(int i=head[s];i;i=e[i].pre)
{
if(!dfn[e[i].v])
{
Tarjan(e[i].v);
low[s]=min(low[s],low[e[i].v]);
}
else if(f[e[i].v])
low[s]=min(low[s],dfn[e[i].v]);
}
if(dfn[s]==low[s])
{
sum++;
while(s!=stack[top])
{
ans[sum].size++;
belong[stack[top]]=sum;
ans[sum].c[ans[sum].size]=stack[top];
f[stack[top]]=;
top--;
}
ans[sum].size++;
belong[stack[top]]=sum;
ans[sum].c[ans[sum].size]=stack[top];
f[stack[top]]=;
top--;
}
}
int main()
{
//freopen("schlnet.in","r",stdin);
//freopen("schlnet.out","w",stdout);
n=init();
int x;
for(int i=;i<=n;i++)
while()
{
x=init();
if(x==)break;
Add(i,x);
}
for(int i=;i<=n;i++)
if(!dfn[i])
Tarjan(i);
for(int i=;i<=n;i++)
{
for(int j=head[i];j;j=e[j].pre)
{
if(belong[i]!=belong[e[j].v])
{
if(g[belong[i]][belong[e[j].v]]==)
{
chu[belong[i]]++;
ru[belong[e[j].v]]++;
}
g[belong[i]][belong[e[j].v]]=;
}
}
}
for(int i=;i<=sum;i++)
{
if(ru[i]==)ans1++;
if(chu[i]==)ans2++;
}
if(sum==)
{
printf("1\n0\n");
return ;
}
printf("%d\n%d\n",ans1,max(ans1,ans2));
return ;
}
上一篇:< high performance web sites > 阅读小记


下一篇:【SICP练习】150 练习4.6