标签:
/* 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=0;char s;bool f=0;s=getchar(); while(s<‘0‘||s>‘9‘){if(s==‘-‘)f=1;s=getchar();} while(s>=‘0‘&&s<=‘9‘){x=x*10+s-‘0‘;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]=1; 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]]=0; top--; } ans[sum].size++; belong[stack[top]]=sum; ans[sum].c[ans[sum].size]=stack[top]; f[stack[top]]=0; top--; } } int main() { //freopen("schlnet.in","r",stdin); //freopen("schlnet.out","w",stdout); n=init(); int x; for(int i=1;i<=n;i++) while(1) { x=init(); if(x==0)break; Add(i,x); } 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;j=e[j].pre) { if(belong[i]!=belong[e[j].v]) { if(g[belong[i]][belong[e[j].v]]==0) { chu[belong[i]]++; ru[belong[e[j].v]]++; } g[belong[i]][belong[e[j].v]]=1; } } } for(int i=1;i<=sum;i++) { if(ru[i]==0)ans1++; if(chu[i]==0)ans2++; } if(sum==1) { printf("1\n0\n"); return 0; } printf("%d\n%d\n",ans1,max(ans1,ans2)); return 0; }
标签:
原文地址:http://www.cnblogs.com/yanlifneg/p/5494567.html